From 645a21ff4fe6f633c428126df3c49267aba0d608 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Wed, 16 Aug 2023 17:16:29 +0200 Subject: [PATCH 01/21] Refactor InboundHandler into smaller Methods (#98444) I tried to go through this code with someone and it became evident that the massive method for request handling is very hard to grok. I split it up into its logical constituents here and fixed some redundant passing around of `message` and `header`. This at least makes it so we only have one layer of ref count handling per method and it is a little easier to follow where forking happens. Also, this removes a weirdly long multi-second compile task from C2 for whatever that's worth :) Also: * fixed `assertRemoteVersion` to be a proper assertion method * extracted `verifyRequestReadFully` since it's not essential to the logic just like we have `verifyResponseReadFully` --- .../transport/InboundHandler.java | 366 ++++++++++-------- .../transport/TransportLogger.java | 2 +- 2 files changed, 202 insertions(+), 166 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/transport/InboundHandler.java b/server/src/main/java/org/elasticsearch/transport/InboundHandler.java index 4bbdb7a3dd779..2080f89d25ccc 100644 --- a/server/src/main/java/org/elasticsearch/transport/InboundHandler.java +++ b/server/src/main/java/org/elasticsearch/transport/InboundHandler.java @@ -106,46 +106,20 @@ private void messageReceived(TcpChannel channel, InboundMessage message, long st assert header.needsToReadVariableHeader() == false; TransportResponseHandler responseHandler = null; - final boolean isRequest = message.getHeader().isRequest(); - ThreadContext threadContext = threadPool.getThreadContext(); try (ThreadContext.StoredContext existing = threadContext.stashContext()) { // Place the context with the headers from the message threadContext.setHeaders(header.getHeaders()); threadContext.putTransient("_remote_address", remoteAddress); - if (isRequest) { - handleRequest(channel, header, message); + if (header.isRequest()) { + handleRequest(channel, message); } else { // Responses do not support short circuiting currently assert message.isShortCircuit() == false; - long requestId = header.getRequestId(); - if (header.isHandshake()) { - responseHandler = handshaker.removeHandlerForHandshake(requestId); - } else { - final TransportResponseHandler theHandler = responseHandlers.onResponseReceived( - requestId, - messageListener - ); - if (theHandler == null && header.isError()) { - responseHandler = handshaker.removeHandlerForHandshake(requestId); - } else { - responseHandler = theHandler; - } - } + responseHandler = findResponseHandler(header); // ignore if its null, the service logs it if (responseHandler != null) { - if (message.getContentLength() > 0 || header.getVersion().equals(TransportVersion.current()) == false) { - final StreamInput streamInput = namedWriteableStream(message.openOrGetStreamInput()); - assertRemoteVersion(streamInput, header.getVersion()); - if (header.isError()) { - handlerResponseError(streamInput, message, responseHandler); - } else { - handleResponse(remoteAddress, streamInput, responseHandler, message); - } - } else { - assert header.isError() == false; - handleResponse(remoteAddress, EMPTY_STREAM_INPUT, responseHandler, message); - } + executeResponseHandler(message, responseHandler, remoteAddress); } } } finally { @@ -153,23 +127,75 @@ private void messageReceived(TcpChannel channel, InboundMessage message, long st handlingTimeTracker.addHandlingTime(took); final long logThreshold = slowLogThresholdMs; if (logThreshold > 0 && took > logThreshold) { - if (isRequest) { - logger.warn( - "handling request [{}] took [{}ms] which is above the warn threshold of [{}ms]", - message, - took, - logThreshold - ); - } else { - logger.warn( - "handling response [{}] on handler [{}] took [{}ms] which is above the warn threshold of [{}ms]", - message, - responseHandler, - took, - logThreshold - ); - } + logSlowMessage(message, took, logThreshold, responseHandler); + } + } + } + + private void executeResponseHandler( + InboundMessage message, + TransportResponseHandler responseHandler, + InetSocketAddress remoteAddress + ) throws IOException { + final var header = message.getHeader(); + if (message.getContentLength() > 0 || header.getVersion().equals(TransportVersion.current()) == false) { + final StreamInput streamInput = namedWriteableStream(message.openOrGetStreamInput()); + assert assertRemoteVersion(streamInput, header.getVersion()); + if (header.isError()) { + handlerResponseError(streamInput, message, responseHandler); + } else { + handleResponse(remoteAddress, streamInput, responseHandler, message); } + } else { + assert header.isError() == false; + handleResponse(remoteAddress, EMPTY_STREAM_INPUT, responseHandler, message); + } + } + + private TransportResponseHandler findResponseHandler(Header header) { + if (header.isHandshake()) { + return handshaker.removeHandlerForHandshake(header.getRequestId()); + } + final TransportResponseHandler theHandler = responseHandlers.onResponseReceived( + header.getRequestId(), + messageListener + ); + if (theHandler == null && header.isError()) { + return handshaker.removeHandlerForHandshake(header.getRequestId()); + } else { + return theHandler; + } + } + + private static void logSlowMessage(InboundMessage message, long took, long logThreshold, TransportResponseHandler responseHandler) { + if (message.getHeader().isRequest()) { + logger.warn("handling request [{}] took [{}ms] which is above the warn threshold of [{}ms]", message, took, logThreshold); + } else { + logger.warn( + "handling response [{}] on handler [{}] took [{}ms] which is above the warn threshold of [{}ms]", + message, + responseHandler, + took, + logThreshold + ); + } + } + + private void verifyRequestReadFully(StreamInput stream, long requestId, String action) throws IOException { + final int nextByte = stream.read(); + // calling read() is useful to make sure the message is fully read, even if there some kind of EOS marker + if (nextByte != -1) { + final IllegalStateException exception = new IllegalStateException( + "Message not fully read (request) for requestId [" + + requestId + + "], action [" + + action + + "], available [" + + stream.available() + + "]; resetting" + ); + assert ignoreDeserializationErrors : exception; + throw exception; } } @@ -193,139 +219,148 @@ private void verifyResponseReadFully(Header header, TransportResponseHandler } } - private void handleRequest(TcpChannel channel, Header header, InboundMessage message) throws IOException { + private void handleRequest(TcpChannel channel, InboundMessage message) throws IOException { + final Header header = message.getHeader(); + if (header.isHandshake()) { + handleHandshakeRequest(channel, message); + return; + } + final String action = header.getActionName(); final long requestId = header.getRequestId(); - final TransportVersion version = header.getVersion(); - if (header.isHandshake()) { + final RequestHandlerRegistry reg = requestHandlers.getHandler(action); + assert message.isShortCircuit() || reg != null : action; + final TransportChannel transportChannel = new TcpTransportChannel( + outboundHandler, + channel, + action, + requestId, + header.getVersion(), + header.getCompressionScheme(), + reg == null ? ResponseStatsConsumer.NONE : reg, + false, + message.takeBreakerReleaseControl() + ); + + try { messageListener.onRequestReceived(requestId, action); - // Cannot short circuit handshakes - assert message.isShortCircuit() == false; + if (reg != null) { + reg.addRequestStats(header.getNetworkMessageSize() + TcpHeader.BYTES_REQUIRED_FOR_MESSAGE_SIZE); + } + + if (message.isShortCircuit()) { + sendErrorResponse(action, transportChannel, message.getException()); + return; + } + + assert reg != null; final StreamInput stream = namedWriteableStream(message.openOrGetStreamInput()); - assertRemoteVersion(stream, header.getVersion()); - final TransportChannel transportChannel = new TcpTransportChannel( - outboundHandler, - channel, - action, - requestId, - version, - header.getCompressionScheme(), - ResponseStatsConsumer.NONE, - header.isHandshake(), - message.takeBreakerReleaseControl() - ); + assert assertRemoteVersion(stream, header.getVersion()); + final T request; try { - handshaker.handleHandshake(transportChannel, requestId, stream); + request = reg.newRequest(stream); } catch (Exception e) { - logger.warn(() -> "error processing handshake version [" + version + "] received on [" + channel + "], closing channel", e); - channel.close(); + assert ignoreDeserializationErrors : e; + throw e; } - } else { - final RequestHandlerRegistry reg = requestHandlers.getHandler(action); - assert message.isShortCircuit() || reg != null : action; - final TransportChannel transportChannel = new TcpTransportChannel( - outboundHandler, - channel, - action, - requestId, - version, - header.getCompressionScheme(), - reg == null ? ResponseStatsConsumer.NONE : reg, - header.isHandshake(), - message.takeBreakerReleaseControl() - ); - try { - messageListener.onRequestReceived(requestId, action); - if (reg != null) { - reg.addRequestStats(header.getNetworkMessageSize() + TcpHeader.BYTES_REQUIRED_FOR_MESSAGE_SIZE); + request.remoteAddress(channel.getRemoteAddress()); + assert requestId > 0; + request.setRequestId(requestId); + verifyRequestReadFully(stream, requestId, action); + if (ThreadPool.Names.SAME.equals(reg.getExecutor())) { + try (var ignored = threadPool.getThreadContext().newTraceContext()) { + doHandleRequest(reg, request, transportChannel); + } + } else { + handleRequestForking(request, reg, transportChannel); } + } finally { + request.decRef(); + } + } catch (Exception e) { + sendErrorResponse(action, transportChannel, e); + } + } - if (message.isShortCircuit()) { - sendErrorResponse(action, transportChannel, message.getException()); - } else { - assert reg != null; - final StreamInput stream = namedWriteableStream(message.openOrGetStreamInput()); - assertRemoteVersion(stream, header.getVersion()); - final T request; - try { - request = reg.newRequest(stream); - } catch (Exception e) { - assert ignoreDeserializationErrors : e; - throw e; - } - try { - request.remoteAddress(channel.getRemoteAddress()); - assert requestId > 0; - request.setRequestId(requestId); - // in case we throw an exception, i.e. when the limit is hit, we don't want to verify - final int nextByte = stream.read(); - // calling read() is useful to make sure the message is fully read, even if there some kind of EOS marker - if (nextByte != -1) { - final IllegalStateException exception = new IllegalStateException( - "Message not fully read (request) for requestId [" - + requestId - + "], action [" - + action - + "], available [" - + stream.available() - + "]; resetting" - ); - assert ignoreDeserializationErrors : exception; - throw exception; - } - final String executor = reg.getExecutor(); - if (ThreadPool.Names.SAME.equals(executor)) { - try (var ignored = threadPool.getThreadContext().newTraceContext()) { - try { - reg.processMessageReceived(request, transportChannel); - } catch (Exception e) { - sendErrorResponse(reg.getAction(), transportChannel, e); - } - } - } else { - boolean success = false; - request.incRef(); - try { - threadPool.executor(executor) - .execute(threadPool.getThreadContext().preserveContextWithTracing(new AbstractRunnable() { - @Override - protected void doRun() throws Exception { - reg.processMessageReceived(request, transportChannel); - } - - @Override - public boolean isForceExecution() { - return reg.isForceExecution(); - } - - @Override - public void onFailure(Exception e) { - sendErrorResponse(reg.getAction(), transportChannel, e); - } - - @Override - public void onAfter() { - request.decRef(); - } - })); - success = true; - } finally { - if (success == false) { - request.decRef(); - } - } - } - } finally { - request.decRef(); - } + private static void doHandleRequest(RequestHandlerRegistry reg, T request, TransportChannel channel) { + try { + reg.processMessageReceived(request, channel); + } catch (Exception e) { + sendErrorResponse(reg.getAction(), channel, e); + } + } + + private void handleRequestForking(T request, RequestHandlerRegistry reg, TransportChannel channel) { + boolean success = false; + request.incRef(); + try { + threadPool.executor(reg.getExecutor()).execute(threadPool.getThreadContext().preserveContextWithTracing(new AbstractRunnable() { + @Override + protected void doRun() { + doHandleRequest(reg, request, channel); } - } catch (Exception e) { - sendErrorResponse(action, transportChannel, e); + + @Override + public boolean isForceExecution() { + return reg.isForceExecution(); + } + + @Override + public void onRejection(Exception e) { + sendErrorResponse(reg.getAction(), channel, e); + } + + @Override + public void onFailure(Exception e) { + assert false : e; // shouldn't get here ever, no failures other than rejection by the thread-pool expected + sendErrorResponse(reg.getAction(), channel, e); + } + + @Override + public void onAfter() { + request.decRef(); + } + })); + success = true; + } finally { + if (success == false) { + request.decRef(); } } } + private void handleHandshakeRequest(TcpChannel channel, InboundMessage message) throws IOException { + var header = message.getHeader(); + assert header.actionName.equals(TransportHandshaker.HANDSHAKE_ACTION_NAME); + final long requestId = header.getRequestId(); + messageListener.onRequestReceived(requestId, TransportHandshaker.HANDSHAKE_ACTION_NAME); + // Cannot short circuit handshakes + assert message.isShortCircuit() == false; + final StreamInput stream = namedWriteableStream(message.openOrGetStreamInput()); + assert assertRemoteVersion(stream, header.getVersion()); + final TransportChannel transportChannel = new TcpTransportChannel( + outboundHandler, + channel, + TransportHandshaker.HANDSHAKE_ACTION_NAME, + requestId, + header.getVersion(), + header.getCompressionScheme(), + ResponseStatsConsumer.NONE, + true, + message.takeBreakerReleaseControl() + ); + try { + handshaker.handleHandshake(transportChannel, requestId, stream); + } catch (Exception e) { + logger.warn( + () -> "error processing handshake version [" + header.getVersion() + "] received on [" + channel + "], closing channel", + e + ); + channel.close(); + } + } + private static void sendErrorResponse(String actionName, TransportChannel transportChannel, Exception e) { try { transportChannel.sendResponse(e); @@ -448,8 +483,9 @@ private StreamInput namedWriteableStream(StreamInput delegate) { return new NamedWriteableAwareStreamInput(delegate, namedWriteableRegistry); } - static void assertRemoteVersion(StreamInput in, TransportVersion version) { + static boolean assertRemoteVersion(StreamInput in, TransportVersion version) { assert version.equals(in.getTransportVersion()) : "Stream version [" + in.getTransportVersion() + "] does not match version [" + version + "]"; + return true; } } diff --git a/server/src/main/java/org/elasticsearch/transport/TransportLogger.java b/server/src/main/java/org/elasticsearch/transport/TransportLogger.java index c4b0381ef4523..2d06d53b4dba0 100644 --- a/server/src/main/java/org/elasticsearch/transport/TransportLogger.java +++ b/server/src/main/java/org/elasticsearch/transport/TransportLogger.java @@ -88,7 +88,7 @@ private static String format(TcpChannel channel, BytesReference message, String sb.append(", header size: ").append(streamInput.readInt()).append('B'); } else { streamInput = decompressingStream(status, streamInput); - InboundHandler.assertRemoteVersion(streamInput, version); + assert InboundHandler.assertRemoteVersion(streamInput, version); } // read and discard headers From 014bd33f456469ce9246aa65fb04fff71e9112e6 Mon Sep 17 00:00:00 2001 From: Andrei Stefan Date: Wed, 16 Aug 2023 20:19:40 +0300 Subject: [PATCH 02/21] ESQL: replace the is_null function with IS NULL and IS NOT NULL predicates (#98412) --- docs/reference/esql/esql-functions.asciidoc | 2 - docs/reference/esql/esql-syntax.asciidoc | 16 + .../reference/esql/functions/is_null.asciidoc | 23 - .../resources/blog-ignoreCsvTests.csv-spec | 2 +- .../src/main/resources/boolean.csv-spec | 4 +- .../src/main/resources/conditional.csv-spec | 36 +- .../src/main/resources/docs.csv-spec | 32 - .../src/main/resources/eval.csv-spec | 7 + .../src/main/resources/ints.csv-spec | 2 +- .../src/main/resources/ip.csv-spec | 4 +- .../src/main/resources/row.csv-spec | 7 + .../src/main/resources/show.csv-spec | 2 - .../src/main/resources/version.csv-spec | 8 +- .../esql/src/main/antlr/EsqlBaseLexer.g4 | 1 + .../esql/src/main/antlr/EsqlBaseLexer.tokens | 134 +- .../esql/src/main/antlr/EsqlBaseParser.g4 | 2 +- .../esql/src/main/antlr/EsqlBaseParser.tokens | 134 +- .../function/EsqlFunctionRegistry.java | 3 +- .../xpack/esql/parser/EsqlBaseLexer.interp | 5 +- .../xpack/esql/parser/EsqlBaseLexer.java | 933 ++++++------ .../xpack/esql/parser/EsqlBaseParser.interp | 4 +- .../xpack/esql/parser/EsqlBaseParser.java | 1248 +++++++++-------- .../parser/EsqlBaseParserBaseListener.java | 12 + .../parser/EsqlBaseParserBaseVisitor.java | 7 + .../esql/parser/EsqlBaseParserListener.java | 12 + .../esql/parser/EsqlBaseParserVisitor.java | 7 + .../xpack/esql/parser/EsqlParser.java | 18 + .../xpack/esql/parser/ExpressionBuilder.java | 9 + .../optimizer/LogicalPlanOptimizerTests.java | 2 +- .../esql/parser/StatementParserTests.java | 11 + 30 files changed, 1415 insertions(+), 1272 deletions(-) delete mode 100644 docs/reference/esql/functions/is_null.asciidoc diff --git a/docs/reference/esql/esql-functions.asciidoc b/docs/reference/esql/esql-functions.asciidoc index 6b656202f04b5..2a4b64331390b 100644 --- a/docs/reference/esql/esql-functions.asciidoc +++ b/docs/reference/esql/esql-functions.asciidoc @@ -28,7 +28,6 @@ these functions: * <> * <> * <> -* <> * <> * <> * <> @@ -84,7 +83,6 @@ include::functions/floor.asciidoc[] include::functions/is_finite.asciidoc[] include::functions/is_infinite.asciidoc[] include::functions/is_nan.asciidoc[] -include::functions/is_null.asciidoc[] include::functions/length.asciidoc[] include::functions/log10.asciidoc[] include::functions/mv_avg.asciidoc[] diff --git a/docs/reference/esql/esql-syntax.asciidoc b/docs/reference/esql/esql-syntax.asciidoc index 80a2596e4def3..53d80b9e29ab7 100644 --- a/docs/reference/esql/esql-syntax.asciidoc +++ b/docs/reference/esql/esql-syntax.asciidoc @@ -114,6 +114,22 @@ The following boolean operators are supported: * `OR` * `NOT` +[discrete] +[[esql-predicates]] +=== Predicates + +For NULL comparison use the `IS NULL` and `IS NOT NULL` predicates: + +[source,esql] +---- +include::{esql-specs}/conditional.csv-spec[tag=is-null] +---- + +[source,esql] +---- +include::{esql-specs}/conditional.csv-spec[tag=is-not-null] +---- + [discrete] [[esql-timespan-literals]] === Timespan literals diff --git a/docs/reference/esql/functions/is_null.asciidoc b/docs/reference/esql/functions/is_null.asciidoc deleted file mode 100644 index 1376288eaaebe..0000000000000 --- a/docs/reference/esql/functions/is_null.asciidoc +++ /dev/null @@ -1,23 +0,0 @@ -[[esql-is_null]] -=== `IS_NULL` -Returns a boolean that indicates whether its input is `null`. - -[source.merge.styled,esql] ----- -include::{esql-specs}/docs.csv-spec[tag=isNull] ----- -[%header.monospaced.styled,format=dsv,separator=|] -|=== -include::{esql-specs}/docs.csv-spec[tag=isNull-result] -|=== - -Combine this function with `NOT` to filter out any `null` data: - -[source.merge.styled,esql] ----- -include::{esql-specs}/docs.csv-spec[tag=notIsNull] ----- -[%header.monospaced.styled,format=dsv,separator=|] -|=== -include::{esql-specs}/docs.csv-spec[tag=notIsNull-result] -|=== diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/blog-ignoreCsvTests.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/blog-ignoreCsvTests.csv-spec index 5c0d00262b61e..f670738bd3c49 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/blog-ignoreCsvTests.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/blog-ignoreCsvTests.csv-spec @@ -7,7 +7,7 @@ | EVAL avg_salary = ROUND(avg_salary) | EVAL lang_code = TO_STRING(languages) | ENRICH languages_policy ON lang_code WITH lang = language_name -| WHERE NOT IS_NULL(lang) +| WHERE lang IS NOT NULL | KEEP avg_salary, lang | SORT avg_salary ASC | LIMIT 3 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/boolean.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/boolean.csv-spec index b3367b473ee48..6489d363ed77d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/boolean.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/boolean.csv-spec @@ -34,14 +34,14 @@ avg(salary):double | still_hired:boolean ; statsByAlwaysTrue -from employees | where not(is_null(first_name)) | eval always_true = starts_with(first_name, "") | stats avg(salary) by always_true; +from employees | where first_name is not null | eval always_true = starts_with(first_name, "") | stats avg(salary) by always_true; avg(salary):double | always_true:boolean 48353.72222222222 | true ; statsByAlwaysFalse -from employees | where not(is_null(first_name)) | eval always_false = starts_with(first_name, "nonestartwiththis") | stats avg(salary) by always_false; +from employees | where first_name is not null | eval always_false = starts_with(first_name, "nonestartwiththis") | stats avg(salary) by always_false; avg(salary):double | always_false:boolean 48353.72222222222 | false diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec index 712f5637411ba..7bc5f4b13ae0e 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec @@ -92,7 +92,7 @@ M |10 isNull from employees -| where is_null(gender) +| where gender is null | sort first_name | keep first_name, gender | limit 3; @@ -105,7 +105,7 @@ Duangkaew |null notIsNull from employees -| where not is_null(gender) +| where gender is not null | sort first_name | keep first_name, gender | limit 3; @@ -115,3 +115,35 @@ Alejandro |F Amabile |M Anneke |F ; + +isNullForDocs +// tag::is-null[] +FROM employees +| WHERE birth_date IS NULL +| KEEP first_name, last_name +| SORT first_name +| LIMIT 3 +// end::is-null[] +; + +// tag::is-null-result[] +first_name:keyword|last_name:keyword +Basil |Tramer +Florian |Syrotiuk +Lucien |Rosenbaum +// end::is-null-result[] +; + +isNotNullForDocs +// tag::is-not-null[] +FROM employees +| WHERE is_rehired IS NOT NULL +| STATS count(emp_no) +// end::is-not-null[] +; + +// tag::is-not-null-result[] +count(emp_no):long +84 +// end::is-not-null-result[] +; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec index 97bd7de53fc47..b386e546f9cb8 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec @@ -399,38 +399,6 @@ Saniya |Kalloufi |2.1 |6.9 // end::round-result[] ; -docsIsNull -// tag::isNull[] -FROM employees -| KEEP first_name, last_name -| WHERE IS_NULL(first_name) -// end::isNull[] -| LIMIT 3; - -// tag::isNull-result[] -first_name:keyword | last_name:keyword -null |Demeyer -null |Joslin -null |Reistad -// end::isNull-result[] -; - -docsNotIsNull -// tag::notIsNull[] -FROM employees -| KEEP first_name, last_name -| WHERE NOT IS_NULL(first_name) -// end::notIsNull[] -| LIMIT 3; - -// tag::notIsNull-result[] -first_name:keyword | last_name:keyword -Georgi |Facello -Bezalel |Simmel -Parto |Bamford -// end::notIsNull-result[] -; - dateParse // tag::dateParse[] ROW date_string = "2022-05-06" diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec index 52e38794595db..ba89685716059 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec @@ -101,3 +101,10 @@ Tse Udi Uri ; + +evalWithIsNullIsNotNull +from employees | eval true_bool = null is null, false_bool = null is not null, negated_true = not(null is null), negated_false = not(null is not null) | sort emp_no | limit 1 | keep *true*, *false*, first_name, last_name; + +true_bool:boolean | negated_true:boolean | false_bool:boolean | negated_false:boolean | first_name:keyword | last_name:keyword +true | false | false | true | Georgi | Facello +; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec index 37a1ae34b1a81..0c73e24136a0f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec @@ -25,7 +25,7 @@ emp_no:integer |languages.byte:byte |avg_worked_seconds:long |height:double // `<= 10030` insures going over records where is_null(languages)==true; `in (.., emp_no)` prevents pushing the IN to Lucene inOverNulls -from employees | keep emp_no, languages | where is_null(languages) or emp_no <= 10030 | where languages in (2, 3, emp_no); +from employees | keep emp_no, languages | where languages is null or emp_no <= 10030 | where languages in (2, 3, emp_no); emp_no:integer |languages:integer 10001 |2 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec index d19f9a110383a..d69be91cd2f22 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec @@ -105,7 +105,7 @@ eth2 |epsilon |[fe81::cae2:65ff:fece:feb9, fe82::cae2:65ff:fece ; isNull -from hosts | where is_null(ip0) | keep ip0, ip1; +from hosts | where ip0 is null | keep ip0, ip1; ip0:ip |ip1:ip null |[127.0.0.1, 127.0.0.2, 127.0.0.3] @@ -149,7 +149,7 @@ eth1 |beta |127.0.0.1 |127.0.0.2 ; cidrMatchNullField -from hosts | where is_null(cidr_match(ip0, "127.0.0.2/32")) | keep card, host, ip0, ip1; +from hosts | where cidr_match(ip0, "127.0.0.2/32") is null | keep card, host, ip0, ip1; card:keyword |host:keyword |ip0:ip |ip1:ip eth0 |epsilon |[fe80::cae2:65ff:fece:feb9, fe80::cae2:65ff:fece:fec0, fe80::cae2:65ff:fece:fec1]|fe80::cae2:65ff:fece:fec1 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/row.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/row.csv-spec index 256c11889950e..0c5026413fce9 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/row.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/row.csv-spec @@ -324,3 +324,10 @@ row integers = [+ 1, -2, -300, -2147483648], longs = [1, - 2, -214748 integers:integer | longs:long | longs2:long | doubles:double [1, -2, -300, -2147483648] | [1, -2, -2147483649] | [1, -2, -9223372036854775808] | [1, -0.455, -2.43, 3.4, -0.12, 8] ; + +isNullIsNotNull +row true_bool = null is null, false_bool = null is not null, negated_true = not(null is null), negated_false = not(null is not null); + +true_bool:boolean | false_bool:boolean | negated_true:boolean | negated_false:boolean +true | false | false | true +; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec index ea8cf53384ecf..99991d39cf8d3 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec @@ -32,7 +32,6 @@ floor |floor(arg1) is_finite |is_finite(arg1) is_infinite |is_infinite(arg1) is_nan |is_nan(arg1) -is_null |is_null(arg1) length |length(arg1) log10 |log10(arg1) max |max(arg1) @@ -91,5 +90,4 @@ show functions | where starts_with(name, "is_"); is_finite |is_finite(arg1) is_infinite |is_infinite(arg1) is_nan |is_nan(arg1) -is_null |is_null(arg1) ; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/version.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/version.csv-spec index 0ef16d648c505..b7b3ca1c99d3c 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/version.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/version.csv-spec @@ -194,7 +194,7 @@ c:l |maxid:i |version:v ; groupOrderLimit -FROM apps | WHERE not is_null(version) | STATS c = COUNT(version) BY version | SORT version DESC | DROP c | LIMIT 3; +FROM apps | WHERE version is not null | STATS c = COUNT(version) BY version | SORT version DESC | DROP c | LIMIT 3; version:v bad @@ -289,14 +289,14 @@ idx:i |version:v case FROM apps | EVAL version_text = TO_STR(version) -| WHERE IS_NULL(version) OR version_text LIKE "1*" +| WHERE version IS NULL OR version_text LIKE "1*" | EVAL v = TO_VER(CONCAT("123", TO_STR(version))) | EVAL m = CASE(version > TO_VER("1.1"), 1, 0) | EVAL g = CASE(version > TO_VER("1.3.0"), version, TO_VER("1.3.0")) -| EVAL i = CASE(IS_NULL(version), TO_VER("0.1"), version) +| EVAL i = CASE(version IS NULL, TO_VER("0.1"), version) | EVAL c = CASE( version > TO_VER("1.1"), "high", - IS_NULL(version), "none", + version IS NULL, "none", "low") | SORT version DESC NULLS LAST, id DESC | KEEP v, version, version_text, id, m, g, i, c; diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 index abd2f2de4f6a0..747c1fdcd1921 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 @@ -93,6 +93,7 @@ FIRST : 'first'; LAST : 'last'; LP : '('; IN: 'in'; +IS: 'is'; LIKE: 'like'; NOT : 'not'; NULL : 'null'; diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens index e8040376185f5..d8761f5eb0d73 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens @@ -39,45 +39,46 @@ FIRST=38 LAST=39 LP=40 IN=41 -LIKE=42 -NOT=43 -NULL=44 -NULLS=45 -OR=46 -PARAM=47 -RLIKE=48 -RP=49 -TRUE=50 -INFO=51 -FUNCTIONS=52 -EQ=53 -NEQ=54 -LT=55 -LTE=56 -GT=57 -GTE=58 -PLUS=59 -MINUS=60 -ASTERISK=61 -SLASH=62 -PERCENT=63 -OPENING_BRACKET=64 -CLOSING_BRACKET=65 -UNQUOTED_IDENTIFIER=66 -QUOTED_IDENTIFIER=67 -EXPR_LINE_COMMENT=68 -EXPR_MULTILINE_COMMENT=69 -EXPR_WS=70 -AS=71 -METADATA=72 -ON=73 -WITH=74 -SRC_UNQUOTED_IDENTIFIER=75 -SRC_QUOTED_IDENTIFIER=76 -SRC_LINE_COMMENT=77 -SRC_MULTILINE_COMMENT=78 -SRC_WS=79 -EXPLAIN_PIPE=80 +IS=42 +LIKE=43 +NOT=44 +NULL=45 +NULLS=46 +OR=47 +PARAM=48 +RLIKE=49 +RP=50 +TRUE=51 +INFO=52 +FUNCTIONS=53 +EQ=54 +NEQ=55 +LT=56 +LTE=57 +GT=58 +GTE=59 +PLUS=60 +MINUS=61 +ASTERISK=62 +SLASH=63 +PERCENT=64 +OPENING_BRACKET=65 +CLOSING_BRACKET=66 +UNQUOTED_IDENTIFIER=67 +QUOTED_IDENTIFIER=68 +EXPR_LINE_COMMENT=69 +EXPR_MULTILINE_COMMENT=70 +EXPR_WS=71 +AS=72 +METADATA=73 +ON=74 +WITH=75 +SRC_UNQUOTED_IDENTIFIER=76 +SRC_QUOTED_IDENTIFIER=77 +SRC_LINE_COMMENT=78 +SRC_MULTILINE_COMMENT=79 +SRC_WS=80 +EXPLAIN_PIPE=81 'dissect'=1 'drop'=2 'enrich'=3 @@ -106,30 +107,31 @@ EXPLAIN_PIPE=80 'last'=39 '('=40 'in'=41 -'like'=42 -'not'=43 -'null'=44 -'nulls'=45 -'or'=46 -'?'=47 -'rlike'=48 -')'=49 -'true'=50 -'info'=51 -'functions'=52 -'=='=53 -'!='=54 -'<'=55 -'<='=56 -'>'=57 -'>='=58 -'+'=59 -'-'=60 -'*'=61 -'/'=62 -'%'=63 -']'=65 -'as'=71 -'metadata'=72 -'on'=73 -'with'=74 +'is'=42 +'like'=43 +'not'=44 +'null'=45 +'nulls'=46 +'or'=47 +'?'=48 +'rlike'=49 +')'=50 +'true'=51 +'info'=52 +'functions'=53 +'=='=54 +'!='=55 +'<'=56 +'<='=57 +'>'=58 +'>='=59 +'+'=60 +'-'=61 +'*'=62 +'/'=63 +'%'=64 +']'=66 +'as'=72 +'metadata'=73 +'on'=74 +'with'=75 diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 index 61fb9ab8e1b46..8f07a8a5dcdea 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 @@ -53,6 +53,7 @@ booleanExpression | left=booleanExpression operator=AND right=booleanExpression #logicalBinary | left=booleanExpression operator=OR right=booleanExpression #logicalBinary | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP #logicalIn + | valueExpression IS NOT? NULL #isNull ; regexBooleanExpression @@ -237,6 +238,5 @@ enrichCommand ; enrichWithClause - : (newName=sourceIdentifier ASSIGN)? enrichField=sourceIdentifier ; diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens index e8040376185f5..d8761f5eb0d73 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens @@ -39,45 +39,46 @@ FIRST=38 LAST=39 LP=40 IN=41 -LIKE=42 -NOT=43 -NULL=44 -NULLS=45 -OR=46 -PARAM=47 -RLIKE=48 -RP=49 -TRUE=50 -INFO=51 -FUNCTIONS=52 -EQ=53 -NEQ=54 -LT=55 -LTE=56 -GT=57 -GTE=58 -PLUS=59 -MINUS=60 -ASTERISK=61 -SLASH=62 -PERCENT=63 -OPENING_BRACKET=64 -CLOSING_BRACKET=65 -UNQUOTED_IDENTIFIER=66 -QUOTED_IDENTIFIER=67 -EXPR_LINE_COMMENT=68 -EXPR_MULTILINE_COMMENT=69 -EXPR_WS=70 -AS=71 -METADATA=72 -ON=73 -WITH=74 -SRC_UNQUOTED_IDENTIFIER=75 -SRC_QUOTED_IDENTIFIER=76 -SRC_LINE_COMMENT=77 -SRC_MULTILINE_COMMENT=78 -SRC_WS=79 -EXPLAIN_PIPE=80 +IS=42 +LIKE=43 +NOT=44 +NULL=45 +NULLS=46 +OR=47 +PARAM=48 +RLIKE=49 +RP=50 +TRUE=51 +INFO=52 +FUNCTIONS=53 +EQ=54 +NEQ=55 +LT=56 +LTE=57 +GT=58 +GTE=59 +PLUS=60 +MINUS=61 +ASTERISK=62 +SLASH=63 +PERCENT=64 +OPENING_BRACKET=65 +CLOSING_BRACKET=66 +UNQUOTED_IDENTIFIER=67 +QUOTED_IDENTIFIER=68 +EXPR_LINE_COMMENT=69 +EXPR_MULTILINE_COMMENT=70 +EXPR_WS=71 +AS=72 +METADATA=73 +ON=74 +WITH=75 +SRC_UNQUOTED_IDENTIFIER=76 +SRC_QUOTED_IDENTIFIER=77 +SRC_LINE_COMMENT=78 +SRC_MULTILINE_COMMENT=79 +SRC_WS=80 +EXPLAIN_PIPE=81 'dissect'=1 'drop'=2 'enrich'=3 @@ -106,30 +107,31 @@ EXPLAIN_PIPE=80 'last'=39 '('=40 'in'=41 -'like'=42 -'not'=43 -'null'=44 -'nulls'=45 -'or'=46 -'?'=47 -'rlike'=48 -')'=49 -'true'=50 -'info'=51 -'functions'=52 -'=='=53 -'!='=54 -'<'=55 -'<='=56 -'>'=57 -'>='=58 -'+'=59 -'-'=60 -'*'=61 -'/'=62 -'%'=63 -']'=65 -'as'=71 -'metadata'=72 -'on'=73 -'with'=74 +'is'=42 +'like'=43 +'not'=44 +'null'=45 +'nulls'=46 +'or'=47 +'?'=48 +'rlike'=49 +')'=50 +'true'=51 +'info'=52 +'functions'=53 +'=='=54 +'!='=55 +'<'=56 +'<='=57 +'>'=58 +'>='=59 +'+'=60 +'-'=61 +'*'=62 +'/'=63 +'%'=64 +']'=66 +'as'=72 +'metadata'=73 +'on'=74 +'with'=75 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 605d1f8d193af..9a16435684648 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -73,7 +73,6 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.Trim; import org.elasticsearch.xpack.ql.expression.function.FunctionDefinition; import org.elasticsearch.xpack.ql.expression.function.FunctionRegistry; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; import java.util.Locale; @@ -140,7 +139,7 @@ private FunctionDefinition[][] functions() { def(DateTrunc.class, DateTrunc::new, "date_trunc"), def(Now.class, Now::new, "now") }, // conditional - new FunctionDefinition[] { def(Case.class, Case::new, "case"), def(IsNull.class, IsNull::new, "is_null"), }, + new FunctionDefinition[] { def(Case.class, Case::new, "case") }, // IP new FunctionDefinition[] { def(CIDRMatch.class, CIDRMatch::new, "cidr_match") }, // conversion functions diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp index cba4b4514d38a..12542878c3ed3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp @@ -41,6 +41,7 @@ null 'last' '(' 'in' +'is' 'like' 'not' 'null' @@ -124,6 +125,7 @@ FIRST LAST LP IN +IS LIKE NOT NULL @@ -213,6 +215,7 @@ FIRST LAST LP IN +IS LIKE NOT NULL @@ -269,4 +272,4 @@ EXPRESSION SOURCE_IDENTIFIERS atn: -[4, 0, 80, 759, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 4, 18, 343, 8, 18, 11, 18, 12, 18, 344, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 353, 8, 19, 10, 19, 12, 19, 356, 9, 19, 1, 19, 3, 19, 359, 8, 19, 1, 19, 3, 19, 362, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 371, 8, 20, 10, 20, 12, 20, 374, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 4, 21, 382, 8, 21, 11, 21, 12, 21, 383, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 425, 8, 32, 1, 32, 4, 32, 428, 8, 32, 11, 32, 12, 32, 429, 1, 33, 1, 33, 1, 33, 5, 33, 435, 8, 33, 10, 33, 12, 33, 438, 9, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 5, 33, 446, 8, 33, 10, 33, 12, 33, 449, 9, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33, 456, 8, 33, 1, 33, 3, 33, 459, 8, 33, 3, 33, 461, 8, 33, 1, 34, 4, 34, 464, 8, 34, 11, 34, 12, 34, 465, 1, 35, 4, 35, 469, 8, 35, 11, 35, 12, 35, 470, 1, 35, 1, 35, 5, 35, 475, 8, 35, 10, 35, 12, 35, 478, 9, 35, 1, 35, 1, 35, 4, 35, 482, 8, 35, 11, 35, 12, 35, 483, 1, 35, 4, 35, 487, 8, 35, 11, 35, 12, 35, 488, 1, 35, 1, 35, 5, 35, 493, 8, 35, 10, 35, 12, 35, 496, 9, 35, 3, 35, 498, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 4, 35, 504, 8, 35, 11, 35, 12, 35, 505, 1, 35, 1, 35, 3, 35, 510, 8, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 5, 72, 649, 8, 72, 10, 72, 12, 72, 652, 9, 72, 1, 72, 1, 72, 1, 72, 1, 72, 4, 72, 658, 8, 72, 11, 72, 12, 72, 659, 3, 72, 662, 8, 72, 1, 73, 1, 73, 1, 73, 1, 73, 5, 73, 668, 8, 73, 10, 73, 12, 73, 671, 9, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 4, 86, 733, 8, 86, 11, 86, 12, 86, 734, 1, 87, 4, 87, 738, 8, 87, 11, 87, 12, 87, 739, 1, 87, 1, 87, 3, 87, 744, 8, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 2, 372, 447, 0, 92, 4, 1, 6, 2, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 11, 26, 12, 28, 13, 30, 14, 32, 15, 34, 16, 36, 17, 38, 18, 40, 19, 42, 20, 44, 21, 46, 22, 48, 0, 50, 80, 52, 23, 54, 24, 56, 25, 58, 26, 60, 0, 62, 0, 64, 0, 66, 0, 68, 0, 70, 27, 72, 28, 74, 29, 76, 30, 78, 31, 80, 32, 82, 33, 84, 34, 86, 35, 88, 36, 90, 37, 92, 38, 94, 39, 96, 40, 98, 41, 100, 42, 102, 43, 104, 44, 106, 45, 108, 46, 110, 47, 112, 48, 114, 49, 116, 50, 118, 51, 120, 52, 122, 53, 124, 54, 126, 55, 128, 56, 130, 57, 132, 58, 134, 59, 136, 60, 138, 61, 140, 62, 142, 63, 144, 64, 146, 65, 148, 66, 150, 67, 152, 68, 154, 69, 156, 70, 158, 0, 160, 0, 162, 0, 164, 0, 166, 0, 168, 71, 170, 72, 172, 73, 174, 74, 176, 75, 178, 0, 180, 76, 182, 77, 184, 78, 186, 79, 4, 0, 1, 2, 3, 13, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 5, 0, 34, 34, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 64, 64, 95, 95, 1, 0, 96, 96, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 787, 0, 4, 1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 1, 48, 1, 0, 0, 0, 1, 50, 1, 0, 0, 0, 1, 52, 1, 0, 0, 0, 1, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 2, 58, 1, 0, 0, 0, 2, 70, 1, 0, 0, 0, 2, 72, 1, 0, 0, 0, 2, 74, 1, 0, 0, 0, 2, 76, 1, 0, 0, 0, 2, 78, 1, 0, 0, 0, 2, 80, 1, 0, 0, 0, 2, 82, 1, 0, 0, 0, 2, 84, 1, 0, 0, 0, 2, 86, 1, 0, 0, 0, 2, 88, 1, 0, 0, 0, 2, 90, 1, 0, 0, 0, 2, 92, 1, 0, 0, 0, 2, 94, 1, 0, 0, 0, 2, 96, 1, 0, 0, 0, 2, 98, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 3, 158, 1, 0, 0, 0, 3, 160, 1, 0, 0, 0, 3, 162, 1, 0, 0, 0, 3, 164, 1, 0, 0, 0, 3, 166, 1, 0, 0, 0, 3, 168, 1, 0, 0, 0, 3, 170, 1, 0, 0, 0, 3, 172, 1, 0, 0, 0, 3, 174, 1, 0, 0, 0, 3, 176, 1, 0, 0, 0, 3, 180, 1, 0, 0, 0, 3, 182, 1, 0, 0, 0, 3, 184, 1, 0, 0, 0, 3, 186, 1, 0, 0, 0, 4, 188, 1, 0, 0, 0, 6, 198, 1, 0, 0, 0, 8, 205, 1, 0, 0, 0, 10, 214, 1, 0, 0, 0, 12, 221, 1, 0, 0, 0, 14, 231, 1, 0, 0, 0, 16, 238, 1, 0, 0, 0, 18, 245, 1, 0, 0, 0, 20, 259, 1, 0, 0, 0, 22, 266, 1, 0, 0, 0, 24, 274, 1, 0, 0, 0, 26, 286, 1, 0, 0, 0, 28, 296, 1, 0, 0, 0, 30, 305, 1, 0, 0, 0, 32, 311, 1, 0, 0, 0, 34, 318, 1, 0, 0, 0, 36, 325, 1, 0, 0, 0, 38, 333, 1, 0, 0, 0, 40, 342, 1, 0, 0, 0, 42, 348, 1, 0, 0, 0, 44, 365, 1, 0, 0, 0, 46, 381, 1, 0, 0, 0, 48, 387, 1, 0, 0, 0, 50, 392, 1, 0, 0, 0, 52, 397, 1, 0, 0, 0, 54, 401, 1, 0, 0, 0, 56, 405, 1, 0, 0, 0, 58, 409, 1, 0, 0, 0, 60, 413, 1, 0, 0, 0, 62, 415, 1, 0, 0, 0, 64, 417, 1, 0, 0, 0, 66, 420, 1, 0, 0, 0, 68, 422, 1, 0, 0, 0, 70, 460, 1, 0, 0, 0, 72, 463, 1, 0, 0, 0, 74, 509, 1, 0, 0, 0, 76, 511, 1, 0, 0, 0, 78, 514, 1, 0, 0, 0, 80, 518, 1, 0, 0, 0, 82, 522, 1, 0, 0, 0, 84, 524, 1, 0, 0, 0, 86, 526, 1, 0, 0, 0, 88, 531, 1, 0, 0, 0, 90, 533, 1, 0, 0, 0, 92, 539, 1, 0, 0, 0, 94, 545, 1, 0, 0, 0, 96, 550, 1, 0, 0, 0, 98, 552, 1, 0, 0, 0, 100, 555, 1, 0, 0, 0, 102, 560, 1, 0, 0, 0, 104, 564, 1, 0, 0, 0, 106, 569, 1, 0, 0, 0, 108, 575, 1, 0, 0, 0, 110, 578, 1, 0, 0, 0, 112, 580, 1, 0, 0, 0, 114, 586, 1, 0, 0, 0, 116, 588, 1, 0, 0, 0, 118, 593, 1, 0, 0, 0, 120, 598, 1, 0, 0, 0, 122, 608, 1, 0, 0, 0, 124, 611, 1, 0, 0, 0, 126, 614, 1, 0, 0, 0, 128, 616, 1, 0, 0, 0, 130, 619, 1, 0, 0, 0, 132, 621, 1, 0, 0, 0, 134, 624, 1, 0, 0, 0, 136, 626, 1, 0, 0, 0, 138, 628, 1, 0, 0, 0, 140, 630, 1, 0, 0, 0, 142, 632, 1, 0, 0, 0, 144, 634, 1, 0, 0, 0, 146, 639, 1, 0, 0, 0, 148, 661, 1, 0, 0, 0, 150, 663, 1, 0, 0, 0, 152, 674, 1, 0, 0, 0, 154, 678, 1, 0, 0, 0, 156, 682, 1, 0, 0, 0, 158, 686, 1, 0, 0, 0, 160, 691, 1, 0, 0, 0, 162, 697, 1, 0, 0, 0, 164, 703, 1, 0, 0, 0, 166, 707, 1, 0, 0, 0, 168, 711, 1, 0, 0, 0, 170, 714, 1, 0, 0, 0, 172, 723, 1, 0, 0, 0, 174, 726, 1, 0, 0, 0, 176, 732, 1, 0, 0, 0, 178, 743, 1, 0, 0, 0, 180, 745, 1, 0, 0, 0, 182, 747, 1, 0, 0, 0, 184, 751, 1, 0, 0, 0, 186, 755, 1, 0, 0, 0, 188, 189, 5, 100, 0, 0, 189, 190, 5, 105, 0, 0, 190, 191, 5, 115, 0, 0, 191, 192, 5, 115, 0, 0, 192, 193, 5, 101, 0, 0, 193, 194, 5, 99, 0, 0, 194, 195, 5, 116, 0, 0, 195, 196, 1, 0, 0, 0, 196, 197, 6, 0, 0, 0, 197, 5, 1, 0, 0, 0, 198, 199, 5, 100, 0, 0, 199, 200, 5, 114, 0, 0, 200, 201, 5, 111, 0, 0, 201, 202, 5, 112, 0, 0, 202, 203, 1, 0, 0, 0, 203, 204, 6, 1, 1, 0, 204, 7, 1, 0, 0, 0, 205, 206, 5, 101, 0, 0, 206, 207, 5, 110, 0, 0, 207, 208, 5, 114, 0, 0, 208, 209, 5, 105, 0, 0, 209, 210, 5, 99, 0, 0, 210, 211, 5, 104, 0, 0, 211, 212, 1, 0, 0, 0, 212, 213, 6, 2, 1, 0, 213, 9, 1, 0, 0, 0, 214, 215, 5, 101, 0, 0, 215, 216, 5, 118, 0, 0, 216, 217, 5, 97, 0, 0, 217, 218, 5, 108, 0, 0, 218, 219, 1, 0, 0, 0, 219, 220, 6, 3, 0, 0, 220, 11, 1, 0, 0, 0, 221, 222, 5, 101, 0, 0, 222, 223, 5, 120, 0, 0, 223, 224, 5, 112, 0, 0, 224, 225, 5, 108, 0, 0, 225, 226, 5, 97, 0, 0, 226, 227, 5, 105, 0, 0, 227, 228, 5, 110, 0, 0, 228, 229, 1, 0, 0, 0, 229, 230, 6, 4, 2, 0, 230, 13, 1, 0, 0, 0, 231, 232, 5, 102, 0, 0, 232, 233, 5, 114, 0, 0, 233, 234, 5, 111, 0, 0, 234, 235, 5, 109, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 6, 5, 1, 0, 237, 15, 1, 0, 0, 0, 238, 239, 5, 103, 0, 0, 239, 240, 5, 114, 0, 0, 240, 241, 5, 111, 0, 0, 241, 242, 5, 107, 0, 0, 242, 243, 1, 0, 0, 0, 243, 244, 6, 6, 0, 0, 244, 17, 1, 0, 0, 0, 245, 246, 5, 105, 0, 0, 246, 247, 5, 110, 0, 0, 247, 248, 5, 108, 0, 0, 248, 249, 5, 105, 0, 0, 249, 250, 5, 110, 0, 0, 250, 251, 5, 101, 0, 0, 251, 252, 5, 115, 0, 0, 252, 253, 5, 116, 0, 0, 253, 254, 5, 97, 0, 0, 254, 255, 5, 116, 0, 0, 255, 256, 5, 115, 0, 0, 256, 257, 1, 0, 0, 0, 257, 258, 6, 7, 0, 0, 258, 19, 1, 0, 0, 0, 259, 260, 5, 107, 0, 0, 260, 261, 5, 101, 0, 0, 261, 262, 5, 101, 0, 0, 262, 263, 5, 112, 0, 0, 263, 264, 1, 0, 0, 0, 264, 265, 6, 8, 1, 0, 265, 21, 1, 0, 0, 0, 266, 267, 5, 108, 0, 0, 267, 268, 5, 105, 0, 0, 268, 269, 5, 109, 0, 0, 269, 270, 5, 105, 0, 0, 270, 271, 5, 116, 0, 0, 271, 272, 1, 0, 0, 0, 272, 273, 6, 9, 0, 0, 273, 23, 1, 0, 0, 0, 274, 275, 5, 109, 0, 0, 275, 276, 5, 118, 0, 0, 276, 277, 5, 95, 0, 0, 277, 278, 5, 101, 0, 0, 278, 279, 5, 120, 0, 0, 279, 280, 5, 112, 0, 0, 280, 281, 5, 97, 0, 0, 281, 282, 5, 110, 0, 0, 282, 283, 5, 100, 0, 0, 283, 284, 1, 0, 0, 0, 284, 285, 6, 10, 1, 0, 285, 25, 1, 0, 0, 0, 286, 287, 5, 112, 0, 0, 287, 288, 5, 114, 0, 0, 288, 289, 5, 111, 0, 0, 289, 290, 5, 106, 0, 0, 290, 291, 5, 101, 0, 0, 291, 292, 5, 99, 0, 0, 292, 293, 5, 116, 0, 0, 293, 294, 1, 0, 0, 0, 294, 295, 6, 11, 1, 0, 295, 27, 1, 0, 0, 0, 296, 297, 5, 114, 0, 0, 297, 298, 5, 101, 0, 0, 298, 299, 5, 110, 0, 0, 299, 300, 5, 97, 0, 0, 300, 301, 5, 109, 0, 0, 301, 302, 5, 101, 0, 0, 302, 303, 1, 0, 0, 0, 303, 304, 6, 12, 1, 0, 304, 29, 1, 0, 0, 0, 305, 306, 5, 114, 0, 0, 306, 307, 5, 111, 0, 0, 307, 308, 5, 119, 0, 0, 308, 309, 1, 0, 0, 0, 309, 310, 6, 13, 0, 0, 310, 31, 1, 0, 0, 0, 311, 312, 5, 115, 0, 0, 312, 313, 5, 104, 0, 0, 313, 314, 5, 111, 0, 0, 314, 315, 5, 119, 0, 0, 315, 316, 1, 0, 0, 0, 316, 317, 6, 14, 0, 0, 317, 33, 1, 0, 0, 0, 318, 319, 5, 115, 0, 0, 319, 320, 5, 111, 0, 0, 320, 321, 5, 114, 0, 0, 321, 322, 5, 116, 0, 0, 322, 323, 1, 0, 0, 0, 323, 324, 6, 15, 0, 0, 324, 35, 1, 0, 0, 0, 325, 326, 5, 115, 0, 0, 326, 327, 5, 116, 0, 0, 327, 328, 5, 97, 0, 0, 328, 329, 5, 116, 0, 0, 329, 330, 5, 115, 0, 0, 330, 331, 1, 0, 0, 0, 331, 332, 6, 16, 0, 0, 332, 37, 1, 0, 0, 0, 333, 334, 5, 119, 0, 0, 334, 335, 5, 104, 0, 0, 335, 336, 5, 101, 0, 0, 336, 337, 5, 114, 0, 0, 337, 338, 5, 101, 0, 0, 338, 339, 1, 0, 0, 0, 339, 340, 6, 17, 0, 0, 340, 39, 1, 0, 0, 0, 341, 343, 8, 0, 0, 0, 342, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 346, 1, 0, 0, 0, 346, 347, 6, 18, 0, 0, 347, 41, 1, 0, 0, 0, 348, 349, 5, 47, 0, 0, 349, 350, 5, 47, 0, 0, 350, 354, 1, 0, 0, 0, 351, 353, 8, 1, 0, 0, 352, 351, 1, 0, 0, 0, 353, 356, 1, 0, 0, 0, 354, 352, 1, 0, 0, 0, 354, 355, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 357, 359, 5, 13, 0, 0, 358, 357, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 361, 1, 0, 0, 0, 360, 362, 5, 10, 0, 0, 361, 360, 1, 0, 0, 0, 361, 362, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 364, 6, 19, 3, 0, 364, 43, 1, 0, 0, 0, 365, 366, 5, 47, 0, 0, 366, 367, 5, 42, 0, 0, 367, 372, 1, 0, 0, 0, 368, 371, 3, 44, 20, 0, 369, 371, 9, 0, 0, 0, 370, 368, 1, 0, 0, 0, 370, 369, 1, 0, 0, 0, 371, 374, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 373, 375, 1, 0, 0, 0, 374, 372, 1, 0, 0, 0, 375, 376, 5, 42, 0, 0, 376, 377, 5, 47, 0, 0, 377, 378, 1, 0, 0, 0, 378, 379, 6, 20, 3, 0, 379, 45, 1, 0, 0, 0, 380, 382, 7, 2, 0, 0, 381, 380, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 381, 1, 0, 0, 0, 383, 384, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 386, 6, 21, 3, 0, 386, 47, 1, 0, 0, 0, 387, 388, 5, 91, 0, 0, 388, 389, 1, 0, 0, 0, 389, 390, 6, 22, 4, 0, 390, 391, 6, 22, 5, 0, 391, 49, 1, 0, 0, 0, 392, 393, 5, 124, 0, 0, 393, 394, 1, 0, 0, 0, 394, 395, 6, 23, 6, 0, 395, 396, 6, 23, 7, 0, 396, 51, 1, 0, 0, 0, 397, 398, 3, 46, 21, 0, 398, 399, 1, 0, 0, 0, 399, 400, 6, 24, 3, 0, 400, 53, 1, 0, 0, 0, 401, 402, 3, 42, 19, 0, 402, 403, 1, 0, 0, 0, 403, 404, 6, 25, 3, 0, 404, 55, 1, 0, 0, 0, 405, 406, 3, 44, 20, 0, 406, 407, 1, 0, 0, 0, 407, 408, 6, 26, 3, 0, 408, 57, 1, 0, 0, 0, 409, 410, 5, 124, 0, 0, 410, 411, 1, 0, 0, 0, 411, 412, 6, 27, 7, 0, 412, 59, 1, 0, 0, 0, 413, 414, 7, 3, 0, 0, 414, 61, 1, 0, 0, 0, 415, 416, 7, 4, 0, 0, 416, 63, 1, 0, 0, 0, 417, 418, 5, 92, 0, 0, 418, 419, 7, 5, 0, 0, 419, 65, 1, 0, 0, 0, 420, 421, 8, 6, 0, 0, 421, 67, 1, 0, 0, 0, 422, 424, 7, 7, 0, 0, 423, 425, 7, 8, 0, 0, 424, 423, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 427, 1, 0, 0, 0, 426, 428, 3, 60, 28, 0, 427, 426, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 427, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 69, 1, 0, 0, 0, 431, 436, 5, 34, 0, 0, 432, 435, 3, 64, 30, 0, 433, 435, 3, 66, 31, 0, 434, 432, 1, 0, 0, 0, 434, 433, 1, 0, 0, 0, 435, 438, 1, 0, 0, 0, 436, 434, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 439, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 439, 461, 5, 34, 0, 0, 440, 441, 5, 34, 0, 0, 441, 442, 5, 34, 0, 0, 442, 443, 5, 34, 0, 0, 443, 447, 1, 0, 0, 0, 444, 446, 8, 1, 0, 0, 445, 444, 1, 0, 0, 0, 446, 449, 1, 0, 0, 0, 447, 448, 1, 0, 0, 0, 447, 445, 1, 0, 0, 0, 448, 450, 1, 0, 0, 0, 449, 447, 1, 0, 0, 0, 450, 451, 5, 34, 0, 0, 451, 452, 5, 34, 0, 0, 452, 453, 5, 34, 0, 0, 453, 455, 1, 0, 0, 0, 454, 456, 5, 34, 0, 0, 455, 454, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 458, 1, 0, 0, 0, 457, 459, 5, 34, 0, 0, 458, 457, 1, 0, 0, 0, 458, 459, 1, 0, 0, 0, 459, 461, 1, 0, 0, 0, 460, 431, 1, 0, 0, 0, 460, 440, 1, 0, 0, 0, 461, 71, 1, 0, 0, 0, 462, 464, 3, 60, 28, 0, 463, 462, 1, 0, 0, 0, 464, 465, 1, 0, 0, 0, 465, 463, 1, 0, 0, 0, 465, 466, 1, 0, 0, 0, 466, 73, 1, 0, 0, 0, 467, 469, 3, 60, 28, 0, 468, 467, 1, 0, 0, 0, 469, 470, 1, 0, 0, 0, 470, 468, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 472, 1, 0, 0, 0, 472, 476, 3, 88, 42, 0, 473, 475, 3, 60, 28, 0, 474, 473, 1, 0, 0, 0, 475, 478, 1, 0, 0, 0, 476, 474, 1, 0, 0, 0, 476, 477, 1, 0, 0, 0, 477, 510, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 479, 481, 3, 88, 42, 0, 480, 482, 3, 60, 28, 0, 481, 480, 1, 0, 0, 0, 482, 483, 1, 0, 0, 0, 483, 481, 1, 0, 0, 0, 483, 484, 1, 0, 0, 0, 484, 510, 1, 0, 0, 0, 485, 487, 3, 60, 28, 0, 486, 485, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 497, 1, 0, 0, 0, 490, 494, 3, 88, 42, 0, 491, 493, 3, 60, 28, 0, 492, 491, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 498, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 490, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 3, 68, 32, 0, 500, 510, 1, 0, 0, 0, 501, 503, 3, 88, 42, 0, 502, 504, 3, 60, 28, 0, 503, 502, 1, 0, 0, 0, 504, 505, 1, 0, 0, 0, 505, 503, 1, 0, 0, 0, 505, 506, 1, 0, 0, 0, 506, 507, 1, 0, 0, 0, 507, 508, 3, 68, 32, 0, 508, 510, 1, 0, 0, 0, 509, 468, 1, 0, 0, 0, 509, 479, 1, 0, 0, 0, 509, 486, 1, 0, 0, 0, 509, 501, 1, 0, 0, 0, 510, 75, 1, 0, 0, 0, 511, 512, 5, 98, 0, 0, 512, 513, 5, 121, 0, 0, 513, 77, 1, 0, 0, 0, 514, 515, 5, 97, 0, 0, 515, 516, 5, 110, 0, 0, 516, 517, 5, 100, 0, 0, 517, 79, 1, 0, 0, 0, 518, 519, 5, 97, 0, 0, 519, 520, 5, 115, 0, 0, 520, 521, 5, 99, 0, 0, 521, 81, 1, 0, 0, 0, 522, 523, 5, 61, 0, 0, 523, 83, 1, 0, 0, 0, 524, 525, 5, 44, 0, 0, 525, 85, 1, 0, 0, 0, 526, 527, 5, 100, 0, 0, 527, 528, 5, 101, 0, 0, 528, 529, 5, 115, 0, 0, 529, 530, 5, 99, 0, 0, 530, 87, 1, 0, 0, 0, 531, 532, 5, 46, 0, 0, 532, 89, 1, 0, 0, 0, 533, 534, 5, 102, 0, 0, 534, 535, 5, 97, 0, 0, 535, 536, 5, 108, 0, 0, 536, 537, 5, 115, 0, 0, 537, 538, 5, 101, 0, 0, 538, 91, 1, 0, 0, 0, 539, 540, 5, 102, 0, 0, 540, 541, 5, 105, 0, 0, 541, 542, 5, 114, 0, 0, 542, 543, 5, 115, 0, 0, 543, 544, 5, 116, 0, 0, 544, 93, 1, 0, 0, 0, 545, 546, 5, 108, 0, 0, 546, 547, 5, 97, 0, 0, 547, 548, 5, 115, 0, 0, 548, 549, 5, 116, 0, 0, 549, 95, 1, 0, 0, 0, 550, 551, 5, 40, 0, 0, 551, 97, 1, 0, 0, 0, 552, 553, 5, 105, 0, 0, 553, 554, 5, 110, 0, 0, 554, 99, 1, 0, 0, 0, 555, 556, 5, 108, 0, 0, 556, 557, 5, 105, 0, 0, 557, 558, 5, 107, 0, 0, 558, 559, 5, 101, 0, 0, 559, 101, 1, 0, 0, 0, 560, 561, 5, 110, 0, 0, 561, 562, 5, 111, 0, 0, 562, 563, 5, 116, 0, 0, 563, 103, 1, 0, 0, 0, 564, 565, 5, 110, 0, 0, 565, 566, 5, 117, 0, 0, 566, 567, 5, 108, 0, 0, 567, 568, 5, 108, 0, 0, 568, 105, 1, 0, 0, 0, 569, 570, 5, 110, 0, 0, 570, 571, 5, 117, 0, 0, 571, 572, 5, 108, 0, 0, 572, 573, 5, 108, 0, 0, 573, 574, 5, 115, 0, 0, 574, 107, 1, 0, 0, 0, 575, 576, 5, 111, 0, 0, 576, 577, 5, 114, 0, 0, 577, 109, 1, 0, 0, 0, 578, 579, 5, 63, 0, 0, 579, 111, 1, 0, 0, 0, 580, 581, 5, 114, 0, 0, 581, 582, 5, 108, 0, 0, 582, 583, 5, 105, 0, 0, 583, 584, 5, 107, 0, 0, 584, 585, 5, 101, 0, 0, 585, 113, 1, 0, 0, 0, 586, 587, 5, 41, 0, 0, 587, 115, 1, 0, 0, 0, 588, 589, 5, 116, 0, 0, 589, 590, 5, 114, 0, 0, 590, 591, 5, 117, 0, 0, 591, 592, 5, 101, 0, 0, 592, 117, 1, 0, 0, 0, 593, 594, 5, 105, 0, 0, 594, 595, 5, 110, 0, 0, 595, 596, 5, 102, 0, 0, 596, 597, 5, 111, 0, 0, 597, 119, 1, 0, 0, 0, 598, 599, 5, 102, 0, 0, 599, 600, 5, 117, 0, 0, 600, 601, 5, 110, 0, 0, 601, 602, 5, 99, 0, 0, 602, 603, 5, 116, 0, 0, 603, 604, 5, 105, 0, 0, 604, 605, 5, 111, 0, 0, 605, 606, 5, 110, 0, 0, 606, 607, 5, 115, 0, 0, 607, 121, 1, 0, 0, 0, 608, 609, 5, 61, 0, 0, 609, 610, 5, 61, 0, 0, 610, 123, 1, 0, 0, 0, 611, 612, 5, 33, 0, 0, 612, 613, 5, 61, 0, 0, 613, 125, 1, 0, 0, 0, 614, 615, 5, 60, 0, 0, 615, 127, 1, 0, 0, 0, 616, 617, 5, 60, 0, 0, 617, 618, 5, 61, 0, 0, 618, 129, 1, 0, 0, 0, 619, 620, 5, 62, 0, 0, 620, 131, 1, 0, 0, 0, 621, 622, 5, 62, 0, 0, 622, 623, 5, 61, 0, 0, 623, 133, 1, 0, 0, 0, 624, 625, 5, 43, 0, 0, 625, 135, 1, 0, 0, 0, 626, 627, 5, 45, 0, 0, 627, 137, 1, 0, 0, 0, 628, 629, 5, 42, 0, 0, 629, 139, 1, 0, 0, 0, 630, 631, 5, 47, 0, 0, 631, 141, 1, 0, 0, 0, 632, 633, 5, 37, 0, 0, 633, 143, 1, 0, 0, 0, 634, 635, 5, 91, 0, 0, 635, 636, 1, 0, 0, 0, 636, 637, 6, 70, 0, 0, 637, 638, 6, 70, 0, 0, 638, 145, 1, 0, 0, 0, 639, 640, 5, 93, 0, 0, 640, 641, 1, 0, 0, 0, 641, 642, 6, 71, 7, 0, 642, 643, 6, 71, 7, 0, 643, 147, 1, 0, 0, 0, 644, 650, 3, 62, 29, 0, 645, 649, 3, 62, 29, 0, 646, 649, 3, 60, 28, 0, 647, 649, 5, 95, 0, 0, 648, 645, 1, 0, 0, 0, 648, 646, 1, 0, 0, 0, 648, 647, 1, 0, 0, 0, 649, 652, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 662, 1, 0, 0, 0, 652, 650, 1, 0, 0, 0, 653, 657, 7, 9, 0, 0, 654, 658, 3, 62, 29, 0, 655, 658, 3, 60, 28, 0, 656, 658, 5, 95, 0, 0, 657, 654, 1, 0, 0, 0, 657, 655, 1, 0, 0, 0, 657, 656, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 662, 1, 0, 0, 0, 661, 644, 1, 0, 0, 0, 661, 653, 1, 0, 0, 0, 662, 149, 1, 0, 0, 0, 663, 669, 5, 96, 0, 0, 664, 668, 8, 10, 0, 0, 665, 666, 5, 96, 0, 0, 666, 668, 5, 96, 0, 0, 667, 664, 1, 0, 0, 0, 667, 665, 1, 0, 0, 0, 668, 671, 1, 0, 0, 0, 669, 667, 1, 0, 0, 0, 669, 670, 1, 0, 0, 0, 670, 672, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 672, 673, 5, 96, 0, 0, 673, 151, 1, 0, 0, 0, 674, 675, 3, 42, 19, 0, 675, 676, 1, 0, 0, 0, 676, 677, 6, 74, 3, 0, 677, 153, 1, 0, 0, 0, 678, 679, 3, 44, 20, 0, 679, 680, 1, 0, 0, 0, 680, 681, 6, 75, 3, 0, 681, 155, 1, 0, 0, 0, 682, 683, 3, 46, 21, 0, 683, 684, 1, 0, 0, 0, 684, 685, 6, 76, 3, 0, 685, 157, 1, 0, 0, 0, 686, 687, 5, 124, 0, 0, 687, 688, 1, 0, 0, 0, 688, 689, 6, 77, 6, 0, 689, 690, 6, 77, 7, 0, 690, 159, 1, 0, 0, 0, 691, 692, 5, 91, 0, 0, 692, 693, 1, 0, 0, 0, 693, 694, 6, 78, 4, 0, 694, 695, 6, 78, 1, 0, 695, 696, 6, 78, 1, 0, 696, 161, 1, 0, 0, 0, 697, 698, 5, 93, 0, 0, 698, 699, 1, 0, 0, 0, 699, 700, 6, 79, 7, 0, 700, 701, 6, 79, 7, 0, 701, 702, 6, 79, 8, 0, 702, 163, 1, 0, 0, 0, 703, 704, 5, 44, 0, 0, 704, 705, 1, 0, 0, 0, 705, 706, 6, 80, 9, 0, 706, 165, 1, 0, 0, 0, 707, 708, 5, 61, 0, 0, 708, 709, 1, 0, 0, 0, 709, 710, 6, 81, 10, 0, 710, 167, 1, 0, 0, 0, 711, 712, 5, 97, 0, 0, 712, 713, 5, 115, 0, 0, 713, 169, 1, 0, 0, 0, 714, 715, 5, 109, 0, 0, 715, 716, 5, 101, 0, 0, 716, 717, 5, 116, 0, 0, 717, 718, 5, 97, 0, 0, 718, 719, 5, 100, 0, 0, 719, 720, 5, 97, 0, 0, 720, 721, 5, 116, 0, 0, 721, 722, 5, 97, 0, 0, 722, 171, 1, 0, 0, 0, 723, 724, 5, 111, 0, 0, 724, 725, 5, 110, 0, 0, 725, 173, 1, 0, 0, 0, 726, 727, 5, 119, 0, 0, 727, 728, 5, 105, 0, 0, 728, 729, 5, 116, 0, 0, 729, 730, 5, 104, 0, 0, 730, 175, 1, 0, 0, 0, 731, 733, 3, 178, 87, 0, 732, 731, 1, 0, 0, 0, 733, 734, 1, 0, 0, 0, 734, 732, 1, 0, 0, 0, 734, 735, 1, 0, 0, 0, 735, 177, 1, 0, 0, 0, 736, 738, 8, 11, 0, 0, 737, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 737, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 744, 1, 0, 0, 0, 741, 742, 5, 47, 0, 0, 742, 744, 8, 12, 0, 0, 743, 737, 1, 0, 0, 0, 743, 741, 1, 0, 0, 0, 744, 179, 1, 0, 0, 0, 745, 746, 3, 150, 73, 0, 746, 181, 1, 0, 0, 0, 747, 748, 3, 42, 19, 0, 748, 749, 1, 0, 0, 0, 749, 750, 6, 89, 3, 0, 750, 183, 1, 0, 0, 0, 751, 752, 3, 44, 20, 0, 752, 753, 1, 0, 0, 0, 753, 754, 6, 90, 3, 0, 754, 185, 1, 0, 0, 0, 755, 756, 3, 46, 21, 0, 756, 757, 1, 0, 0, 0, 757, 758, 6, 91, 3, 0, 758, 187, 1, 0, 0, 0, 38, 0, 1, 2, 3, 344, 354, 358, 361, 370, 372, 383, 424, 429, 434, 436, 447, 455, 458, 460, 465, 470, 476, 483, 488, 494, 497, 505, 509, 648, 650, 657, 659, 661, 667, 669, 734, 739, 743, 11, 5, 2, 0, 5, 3, 0, 5, 1, 0, 0, 1, 0, 7, 64, 0, 5, 0, 0, 7, 26, 0, 4, 0, 0, 7, 65, 0, 7, 34, 0, 7, 33, 0] \ No newline at end of file +[4, 0, 81, 764, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 4, 18, 345, 8, 18, 11, 18, 12, 18, 346, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 355, 8, 19, 10, 19, 12, 19, 358, 9, 19, 1, 19, 3, 19, 361, 8, 19, 1, 19, 3, 19, 364, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 373, 8, 20, 10, 20, 12, 20, 376, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 4, 21, 384, 8, 21, 11, 21, 12, 21, 385, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 427, 8, 32, 1, 32, 4, 32, 430, 8, 32, 11, 32, 12, 32, 431, 1, 33, 1, 33, 1, 33, 5, 33, 437, 8, 33, 10, 33, 12, 33, 440, 9, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 5, 33, 448, 8, 33, 10, 33, 12, 33, 451, 9, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33, 458, 8, 33, 1, 33, 3, 33, 461, 8, 33, 3, 33, 463, 8, 33, 1, 34, 4, 34, 466, 8, 34, 11, 34, 12, 34, 467, 1, 35, 4, 35, 471, 8, 35, 11, 35, 12, 35, 472, 1, 35, 1, 35, 5, 35, 477, 8, 35, 10, 35, 12, 35, 480, 9, 35, 1, 35, 1, 35, 4, 35, 484, 8, 35, 11, 35, 12, 35, 485, 1, 35, 4, 35, 489, 8, 35, 11, 35, 12, 35, 490, 1, 35, 1, 35, 5, 35, 495, 8, 35, 10, 35, 12, 35, 498, 9, 35, 3, 35, 500, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 4, 35, 506, 8, 35, 11, 35, 12, 35, 507, 1, 35, 1, 35, 3, 35, 512, 8, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 5, 73, 654, 8, 73, 10, 73, 12, 73, 657, 9, 73, 1, 73, 1, 73, 1, 73, 1, 73, 4, 73, 663, 8, 73, 11, 73, 12, 73, 664, 3, 73, 667, 8, 73, 1, 74, 1, 74, 1, 74, 1, 74, 5, 74, 673, 8, 74, 10, 74, 12, 74, 676, 9, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 4, 87, 738, 8, 87, 11, 87, 12, 87, 739, 1, 88, 4, 88, 743, 8, 88, 11, 88, 12, 88, 744, 1, 88, 1, 88, 3, 88, 749, 8, 88, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 2, 374, 449, 0, 93, 4, 1, 6, 2, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 11, 26, 12, 28, 13, 30, 14, 32, 15, 34, 16, 36, 17, 38, 18, 40, 19, 42, 20, 44, 21, 46, 22, 48, 0, 50, 81, 52, 23, 54, 24, 56, 25, 58, 26, 60, 0, 62, 0, 64, 0, 66, 0, 68, 0, 70, 27, 72, 28, 74, 29, 76, 30, 78, 31, 80, 32, 82, 33, 84, 34, 86, 35, 88, 36, 90, 37, 92, 38, 94, 39, 96, 40, 98, 41, 100, 42, 102, 43, 104, 44, 106, 45, 108, 46, 110, 47, 112, 48, 114, 49, 116, 50, 118, 51, 120, 52, 122, 53, 124, 54, 126, 55, 128, 56, 130, 57, 132, 58, 134, 59, 136, 60, 138, 61, 140, 62, 142, 63, 144, 64, 146, 65, 148, 66, 150, 67, 152, 68, 154, 69, 156, 70, 158, 71, 160, 0, 162, 0, 164, 0, 166, 0, 168, 0, 170, 72, 172, 73, 174, 74, 176, 75, 178, 76, 180, 0, 182, 77, 184, 78, 186, 79, 188, 80, 4, 0, 1, 2, 3, 13, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 5, 0, 34, 34, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 64, 64, 95, 95, 1, 0, 96, 96, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 792, 0, 4, 1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 1, 48, 1, 0, 0, 0, 1, 50, 1, 0, 0, 0, 1, 52, 1, 0, 0, 0, 1, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 2, 58, 1, 0, 0, 0, 2, 70, 1, 0, 0, 0, 2, 72, 1, 0, 0, 0, 2, 74, 1, 0, 0, 0, 2, 76, 1, 0, 0, 0, 2, 78, 1, 0, 0, 0, 2, 80, 1, 0, 0, 0, 2, 82, 1, 0, 0, 0, 2, 84, 1, 0, 0, 0, 2, 86, 1, 0, 0, 0, 2, 88, 1, 0, 0, 0, 2, 90, 1, 0, 0, 0, 2, 92, 1, 0, 0, 0, 2, 94, 1, 0, 0, 0, 2, 96, 1, 0, 0, 0, 2, 98, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 2, 158, 1, 0, 0, 0, 3, 160, 1, 0, 0, 0, 3, 162, 1, 0, 0, 0, 3, 164, 1, 0, 0, 0, 3, 166, 1, 0, 0, 0, 3, 168, 1, 0, 0, 0, 3, 170, 1, 0, 0, 0, 3, 172, 1, 0, 0, 0, 3, 174, 1, 0, 0, 0, 3, 176, 1, 0, 0, 0, 3, 178, 1, 0, 0, 0, 3, 182, 1, 0, 0, 0, 3, 184, 1, 0, 0, 0, 3, 186, 1, 0, 0, 0, 3, 188, 1, 0, 0, 0, 4, 190, 1, 0, 0, 0, 6, 200, 1, 0, 0, 0, 8, 207, 1, 0, 0, 0, 10, 216, 1, 0, 0, 0, 12, 223, 1, 0, 0, 0, 14, 233, 1, 0, 0, 0, 16, 240, 1, 0, 0, 0, 18, 247, 1, 0, 0, 0, 20, 261, 1, 0, 0, 0, 22, 268, 1, 0, 0, 0, 24, 276, 1, 0, 0, 0, 26, 288, 1, 0, 0, 0, 28, 298, 1, 0, 0, 0, 30, 307, 1, 0, 0, 0, 32, 313, 1, 0, 0, 0, 34, 320, 1, 0, 0, 0, 36, 327, 1, 0, 0, 0, 38, 335, 1, 0, 0, 0, 40, 344, 1, 0, 0, 0, 42, 350, 1, 0, 0, 0, 44, 367, 1, 0, 0, 0, 46, 383, 1, 0, 0, 0, 48, 389, 1, 0, 0, 0, 50, 394, 1, 0, 0, 0, 52, 399, 1, 0, 0, 0, 54, 403, 1, 0, 0, 0, 56, 407, 1, 0, 0, 0, 58, 411, 1, 0, 0, 0, 60, 415, 1, 0, 0, 0, 62, 417, 1, 0, 0, 0, 64, 419, 1, 0, 0, 0, 66, 422, 1, 0, 0, 0, 68, 424, 1, 0, 0, 0, 70, 462, 1, 0, 0, 0, 72, 465, 1, 0, 0, 0, 74, 511, 1, 0, 0, 0, 76, 513, 1, 0, 0, 0, 78, 516, 1, 0, 0, 0, 80, 520, 1, 0, 0, 0, 82, 524, 1, 0, 0, 0, 84, 526, 1, 0, 0, 0, 86, 528, 1, 0, 0, 0, 88, 533, 1, 0, 0, 0, 90, 535, 1, 0, 0, 0, 92, 541, 1, 0, 0, 0, 94, 547, 1, 0, 0, 0, 96, 552, 1, 0, 0, 0, 98, 554, 1, 0, 0, 0, 100, 557, 1, 0, 0, 0, 102, 560, 1, 0, 0, 0, 104, 565, 1, 0, 0, 0, 106, 569, 1, 0, 0, 0, 108, 574, 1, 0, 0, 0, 110, 580, 1, 0, 0, 0, 112, 583, 1, 0, 0, 0, 114, 585, 1, 0, 0, 0, 116, 591, 1, 0, 0, 0, 118, 593, 1, 0, 0, 0, 120, 598, 1, 0, 0, 0, 122, 603, 1, 0, 0, 0, 124, 613, 1, 0, 0, 0, 126, 616, 1, 0, 0, 0, 128, 619, 1, 0, 0, 0, 130, 621, 1, 0, 0, 0, 132, 624, 1, 0, 0, 0, 134, 626, 1, 0, 0, 0, 136, 629, 1, 0, 0, 0, 138, 631, 1, 0, 0, 0, 140, 633, 1, 0, 0, 0, 142, 635, 1, 0, 0, 0, 144, 637, 1, 0, 0, 0, 146, 639, 1, 0, 0, 0, 148, 644, 1, 0, 0, 0, 150, 666, 1, 0, 0, 0, 152, 668, 1, 0, 0, 0, 154, 679, 1, 0, 0, 0, 156, 683, 1, 0, 0, 0, 158, 687, 1, 0, 0, 0, 160, 691, 1, 0, 0, 0, 162, 696, 1, 0, 0, 0, 164, 702, 1, 0, 0, 0, 166, 708, 1, 0, 0, 0, 168, 712, 1, 0, 0, 0, 170, 716, 1, 0, 0, 0, 172, 719, 1, 0, 0, 0, 174, 728, 1, 0, 0, 0, 176, 731, 1, 0, 0, 0, 178, 737, 1, 0, 0, 0, 180, 748, 1, 0, 0, 0, 182, 750, 1, 0, 0, 0, 184, 752, 1, 0, 0, 0, 186, 756, 1, 0, 0, 0, 188, 760, 1, 0, 0, 0, 190, 191, 5, 100, 0, 0, 191, 192, 5, 105, 0, 0, 192, 193, 5, 115, 0, 0, 193, 194, 5, 115, 0, 0, 194, 195, 5, 101, 0, 0, 195, 196, 5, 99, 0, 0, 196, 197, 5, 116, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 6, 0, 0, 0, 199, 5, 1, 0, 0, 0, 200, 201, 5, 100, 0, 0, 201, 202, 5, 114, 0, 0, 202, 203, 5, 111, 0, 0, 203, 204, 5, 112, 0, 0, 204, 205, 1, 0, 0, 0, 205, 206, 6, 1, 1, 0, 206, 7, 1, 0, 0, 0, 207, 208, 5, 101, 0, 0, 208, 209, 5, 110, 0, 0, 209, 210, 5, 114, 0, 0, 210, 211, 5, 105, 0, 0, 211, 212, 5, 99, 0, 0, 212, 213, 5, 104, 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 6, 2, 1, 0, 215, 9, 1, 0, 0, 0, 216, 217, 5, 101, 0, 0, 217, 218, 5, 118, 0, 0, 218, 219, 5, 97, 0, 0, 219, 220, 5, 108, 0, 0, 220, 221, 1, 0, 0, 0, 221, 222, 6, 3, 0, 0, 222, 11, 1, 0, 0, 0, 223, 224, 5, 101, 0, 0, 224, 225, 5, 120, 0, 0, 225, 226, 5, 112, 0, 0, 226, 227, 5, 108, 0, 0, 227, 228, 5, 97, 0, 0, 228, 229, 5, 105, 0, 0, 229, 230, 5, 110, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 6, 4, 2, 0, 232, 13, 1, 0, 0, 0, 233, 234, 5, 102, 0, 0, 234, 235, 5, 114, 0, 0, 235, 236, 5, 111, 0, 0, 236, 237, 5, 109, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 6, 5, 1, 0, 239, 15, 1, 0, 0, 0, 240, 241, 5, 103, 0, 0, 241, 242, 5, 114, 0, 0, 242, 243, 5, 111, 0, 0, 243, 244, 5, 107, 0, 0, 244, 245, 1, 0, 0, 0, 245, 246, 6, 6, 0, 0, 246, 17, 1, 0, 0, 0, 247, 248, 5, 105, 0, 0, 248, 249, 5, 110, 0, 0, 249, 250, 5, 108, 0, 0, 250, 251, 5, 105, 0, 0, 251, 252, 5, 110, 0, 0, 252, 253, 5, 101, 0, 0, 253, 254, 5, 115, 0, 0, 254, 255, 5, 116, 0, 0, 255, 256, 5, 97, 0, 0, 256, 257, 5, 116, 0, 0, 257, 258, 5, 115, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 6, 7, 0, 0, 260, 19, 1, 0, 0, 0, 261, 262, 5, 107, 0, 0, 262, 263, 5, 101, 0, 0, 263, 264, 5, 101, 0, 0, 264, 265, 5, 112, 0, 0, 265, 266, 1, 0, 0, 0, 266, 267, 6, 8, 1, 0, 267, 21, 1, 0, 0, 0, 268, 269, 5, 108, 0, 0, 269, 270, 5, 105, 0, 0, 270, 271, 5, 109, 0, 0, 271, 272, 5, 105, 0, 0, 272, 273, 5, 116, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 6, 9, 0, 0, 275, 23, 1, 0, 0, 0, 276, 277, 5, 109, 0, 0, 277, 278, 5, 118, 0, 0, 278, 279, 5, 95, 0, 0, 279, 280, 5, 101, 0, 0, 280, 281, 5, 120, 0, 0, 281, 282, 5, 112, 0, 0, 282, 283, 5, 97, 0, 0, 283, 284, 5, 110, 0, 0, 284, 285, 5, 100, 0, 0, 285, 286, 1, 0, 0, 0, 286, 287, 6, 10, 1, 0, 287, 25, 1, 0, 0, 0, 288, 289, 5, 112, 0, 0, 289, 290, 5, 114, 0, 0, 290, 291, 5, 111, 0, 0, 291, 292, 5, 106, 0, 0, 292, 293, 5, 101, 0, 0, 293, 294, 5, 99, 0, 0, 294, 295, 5, 116, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 6, 11, 1, 0, 297, 27, 1, 0, 0, 0, 298, 299, 5, 114, 0, 0, 299, 300, 5, 101, 0, 0, 300, 301, 5, 110, 0, 0, 301, 302, 5, 97, 0, 0, 302, 303, 5, 109, 0, 0, 303, 304, 5, 101, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 6, 12, 1, 0, 306, 29, 1, 0, 0, 0, 307, 308, 5, 114, 0, 0, 308, 309, 5, 111, 0, 0, 309, 310, 5, 119, 0, 0, 310, 311, 1, 0, 0, 0, 311, 312, 6, 13, 0, 0, 312, 31, 1, 0, 0, 0, 313, 314, 5, 115, 0, 0, 314, 315, 5, 104, 0, 0, 315, 316, 5, 111, 0, 0, 316, 317, 5, 119, 0, 0, 317, 318, 1, 0, 0, 0, 318, 319, 6, 14, 0, 0, 319, 33, 1, 0, 0, 0, 320, 321, 5, 115, 0, 0, 321, 322, 5, 111, 0, 0, 322, 323, 5, 114, 0, 0, 323, 324, 5, 116, 0, 0, 324, 325, 1, 0, 0, 0, 325, 326, 6, 15, 0, 0, 326, 35, 1, 0, 0, 0, 327, 328, 5, 115, 0, 0, 328, 329, 5, 116, 0, 0, 329, 330, 5, 97, 0, 0, 330, 331, 5, 116, 0, 0, 331, 332, 5, 115, 0, 0, 332, 333, 1, 0, 0, 0, 333, 334, 6, 16, 0, 0, 334, 37, 1, 0, 0, 0, 335, 336, 5, 119, 0, 0, 336, 337, 5, 104, 0, 0, 337, 338, 5, 101, 0, 0, 338, 339, 5, 114, 0, 0, 339, 340, 5, 101, 0, 0, 340, 341, 1, 0, 0, 0, 341, 342, 6, 17, 0, 0, 342, 39, 1, 0, 0, 0, 343, 345, 8, 0, 0, 0, 344, 343, 1, 0, 0, 0, 345, 346, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 349, 6, 18, 0, 0, 349, 41, 1, 0, 0, 0, 350, 351, 5, 47, 0, 0, 351, 352, 5, 47, 0, 0, 352, 356, 1, 0, 0, 0, 353, 355, 8, 1, 0, 0, 354, 353, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 360, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 359, 361, 5, 13, 0, 0, 360, 359, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 363, 1, 0, 0, 0, 362, 364, 5, 10, 0, 0, 363, 362, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 365, 1, 0, 0, 0, 365, 366, 6, 19, 3, 0, 366, 43, 1, 0, 0, 0, 367, 368, 5, 47, 0, 0, 368, 369, 5, 42, 0, 0, 369, 374, 1, 0, 0, 0, 370, 373, 3, 44, 20, 0, 371, 373, 9, 0, 0, 0, 372, 370, 1, 0, 0, 0, 372, 371, 1, 0, 0, 0, 373, 376, 1, 0, 0, 0, 374, 375, 1, 0, 0, 0, 374, 372, 1, 0, 0, 0, 375, 377, 1, 0, 0, 0, 376, 374, 1, 0, 0, 0, 377, 378, 5, 42, 0, 0, 378, 379, 5, 47, 0, 0, 379, 380, 1, 0, 0, 0, 380, 381, 6, 20, 3, 0, 381, 45, 1, 0, 0, 0, 382, 384, 7, 2, 0, 0, 383, 382, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 383, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 387, 1, 0, 0, 0, 387, 388, 6, 21, 3, 0, 388, 47, 1, 0, 0, 0, 389, 390, 5, 91, 0, 0, 390, 391, 1, 0, 0, 0, 391, 392, 6, 22, 4, 0, 392, 393, 6, 22, 5, 0, 393, 49, 1, 0, 0, 0, 394, 395, 5, 124, 0, 0, 395, 396, 1, 0, 0, 0, 396, 397, 6, 23, 6, 0, 397, 398, 6, 23, 7, 0, 398, 51, 1, 0, 0, 0, 399, 400, 3, 46, 21, 0, 400, 401, 1, 0, 0, 0, 401, 402, 6, 24, 3, 0, 402, 53, 1, 0, 0, 0, 403, 404, 3, 42, 19, 0, 404, 405, 1, 0, 0, 0, 405, 406, 6, 25, 3, 0, 406, 55, 1, 0, 0, 0, 407, 408, 3, 44, 20, 0, 408, 409, 1, 0, 0, 0, 409, 410, 6, 26, 3, 0, 410, 57, 1, 0, 0, 0, 411, 412, 5, 124, 0, 0, 412, 413, 1, 0, 0, 0, 413, 414, 6, 27, 7, 0, 414, 59, 1, 0, 0, 0, 415, 416, 7, 3, 0, 0, 416, 61, 1, 0, 0, 0, 417, 418, 7, 4, 0, 0, 418, 63, 1, 0, 0, 0, 419, 420, 5, 92, 0, 0, 420, 421, 7, 5, 0, 0, 421, 65, 1, 0, 0, 0, 422, 423, 8, 6, 0, 0, 423, 67, 1, 0, 0, 0, 424, 426, 7, 7, 0, 0, 425, 427, 7, 8, 0, 0, 426, 425, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 429, 1, 0, 0, 0, 428, 430, 3, 60, 28, 0, 429, 428, 1, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 429, 1, 0, 0, 0, 431, 432, 1, 0, 0, 0, 432, 69, 1, 0, 0, 0, 433, 438, 5, 34, 0, 0, 434, 437, 3, 64, 30, 0, 435, 437, 3, 66, 31, 0, 436, 434, 1, 0, 0, 0, 436, 435, 1, 0, 0, 0, 437, 440, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 438, 439, 1, 0, 0, 0, 439, 441, 1, 0, 0, 0, 440, 438, 1, 0, 0, 0, 441, 463, 5, 34, 0, 0, 442, 443, 5, 34, 0, 0, 443, 444, 5, 34, 0, 0, 444, 445, 5, 34, 0, 0, 445, 449, 1, 0, 0, 0, 446, 448, 8, 1, 0, 0, 447, 446, 1, 0, 0, 0, 448, 451, 1, 0, 0, 0, 449, 450, 1, 0, 0, 0, 449, 447, 1, 0, 0, 0, 450, 452, 1, 0, 0, 0, 451, 449, 1, 0, 0, 0, 452, 453, 5, 34, 0, 0, 453, 454, 5, 34, 0, 0, 454, 455, 5, 34, 0, 0, 455, 457, 1, 0, 0, 0, 456, 458, 5, 34, 0, 0, 457, 456, 1, 0, 0, 0, 457, 458, 1, 0, 0, 0, 458, 460, 1, 0, 0, 0, 459, 461, 5, 34, 0, 0, 460, 459, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 463, 1, 0, 0, 0, 462, 433, 1, 0, 0, 0, 462, 442, 1, 0, 0, 0, 463, 71, 1, 0, 0, 0, 464, 466, 3, 60, 28, 0, 465, 464, 1, 0, 0, 0, 466, 467, 1, 0, 0, 0, 467, 465, 1, 0, 0, 0, 467, 468, 1, 0, 0, 0, 468, 73, 1, 0, 0, 0, 469, 471, 3, 60, 28, 0, 470, 469, 1, 0, 0, 0, 471, 472, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 478, 3, 88, 42, 0, 475, 477, 3, 60, 28, 0, 476, 475, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 512, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 483, 3, 88, 42, 0, 482, 484, 3, 60, 28, 0, 483, 482, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 483, 1, 0, 0, 0, 485, 486, 1, 0, 0, 0, 486, 512, 1, 0, 0, 0, 487, 489, 3, 60, 28, 0, 488, 487, 1, 0, 0, 0, 489, 490, 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 490, 491, 1, 0, 0, 0, 491, 499, 1, 0, 0, 0, 492, 496, 3, 88, 42, 0, 493, 495, 3, 60, 28, 0, 494, 493, 1, 0, 0, 0, 495, 498, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 500, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 499, 492, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 502, 3, 68, 32, 0, 502, 512, 1, 0, 0, 0, 503, 505, 3, 88, 42, 0, 504, 506, 3, 60, 28, 0, 505, 504, 1, 0, 0, 0, 506, 507, 1, 0, 0, 0, 507, 505, 1, 0, 0, 0, 507, 508, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 510, 3, 68, 32, 0, 510, 512, 1, 0, 0, 0, 511, 470, 1, 0, 0, 0, 511, 481, 1, 0, 0, 0, 511, 488, 1, 0, 0, 0, 511, 503, 1, 0, 0, 0, 512, 75, 1, 0, 0, 0, 513, 514, 5, 98, 0, 0, 514, 515, 5, 121, 0, 0, 515, 77, 1, 0, 0, 0, 516, 517, 5, 97, 0, 0, 517, 518, 5, 110, 0, 0, 518, 519, 5, 100, 0, 0, 519, 79, 1, 0, 0, 0, 520, 521, 5, 97, 0, 0, 521, 522, 5, 115, 0, 0, 522, 523, 5, 99, 0, 0, 523, 81, 1, 0, 0, 0, 524, 525, 5, 61, 0, 0, 525, 83, 1, 0, 0, 0, 526, 527, 5, 44, 0, 0, 527, 85, 1, 0, 0, 0, 528, 529, 5, 100, 0, 0, 529, 530, 5, 101, 0, 0, 530, 531, 5, 115, 0, 0, 531, 532, 5, 99, 0, 0, 532, 87, 1, 0, 0, 0, 533, 534, 5, 46, 0, 0, 534, 89, 1, 0, 0, 0, 535, 536, 5, 102, 0, 0, 536, 537, 5, 97, 0, 0, 537, 538, 5, 108, 0, 0, 538, 539, 5, 115, 0, 0, 539, 540, 5, 101, 0, 0, 540, 91, 1, 0, 0, 0, 541, 542, 5, 102, 0, 0, 542, 543, 5, 105, 0, 0, 543, 544, 5, 114, 0, 0, 544, 545, 5, 115, 0, 0, 545, 546, 5, 116, 0, 0, 546, 93, 1, 0, 0, 0, 547, 548, 5, 108, 0, 0, 548, 549, 5, 97, 0, 0, 549, 550, 5, 115, 0, 0, 550, 551, 5, 116, 0, 0, 551, 95, 1, 0, 0, 0, 552, 553, 5, 40, 0, 0, 553, 97, 1, 0, 0, 0, 554, 555, 5, 105, 0, 0, 555, 556, 5, 110, 0, 0, 556, 99, 1, 0, 0, 0, 557, 558, 5, 105, 0, 0, 558, 559, 5, 115, 0, 0, 559, 101, 1, 0, 0, 0, 560, 561, 5, 108, 0, 0, 561, 562, 5, 105, 0, 0, 562, 563, 5, 107, 0, 0, 563, 564, 5, 101, 0, 0, 564, 103, 1, 0, 0, 0, 565, 566, 5, 110, 0, 0, 566, 567, 5, 111, 0, 0, 567, 568, 5, 116, 0, 0, 568, 105, 1, 0, 0, 0, 569, 570, 5, 110, 0, 0, 570, 571, 5, 117, 0, 0, 571, 572, 5, 108, 0, 0, 572, 573, 5, 108, 0, 0, 573, 107, 1, 0, 0, 0, 574, 575, 5, 110, 0, 0, 575, 576, 5, 117, 0, 0, 576, 577, 5, 108, 0, 0, 577, 578, 5, 108, 0, 0, 578, 579, 5, 115, 0, 0, 579, 109, 1, 0, 0, 0, 580, 581, 5, 111, 0, 0, 581, 582, 5, 114, 0, 0, 582, 111, 1, 0, 0, 0, 583, 584, 5, 63, 0, 0, 584, 113, 1, 0, 0, 0, 585, 586, 5, 114, 0, 0, 586, 587, 5, 108, 0, 0, 587, 588, 5, 105, 0, 0, 588, 589, 5, 107, 0, 0, 589, 590, 5, 101, 0, 0, 590, 115, 1, 0, 0, 0, 591, 592, 5, 41, 0, 0, 592, 117, 1, 0, 0, 0, 593, 594, 5, 116, 0, 0, 594, 595, 5, 114, 0, 0, 595, 596, 5, 117, 0, 0, 596, 597, 5, 101, 0, 0, 597, 119, 1, 0, 0, 0, 598, 599, 5, 105, 0, 0, 599, 600, 5, 110, 0, 0, 600, 601, 5, 102, 0, 0, 601, 602, 5, 111, 0, 0, 602, 121, 1, 0, 0, 0, 603, 604, 5, 102, 0, 0, 604, 605, 5, 117, 0, 0, 605, 606, 5, 110, 0, 0, 606, 607, 5, 99, 0, 0, 607, 608, 5, 116, 0, 0, 608, 609, 5, 105, 0, 0, 609, 610, 5, 111, 0, 0, 610, 611, 5, 110, 0, 0, 611, 612, 5, 115, 0, 0, 612, 123, 1, 0, 0, 0, 613, 614, 5, 61, 0, 0, 614, 615, 5, 61, 0, 0, 615, 125, 1, 0, 0, 0, 616, 617, 5, 33, 0, 0, 617, 618, 5, 61, 0, 0, 618, 127, 1, 0, 0, 0, 619, 620, 5, 60, 0, 0, 620, 129, 1, 0, 0, 0, 621, 622, 5, 60, 0, 0, 622, 623, 5, 61, 0, 0, 623, 131, 1, 0, 0, 0, 624, 625, 5, 62, 0, 0, 625, 133, 1, 0, 0, 0, 626, 627, 5, 62, 0, 0, 627, 628, 5, 61, 0, 0, 628, 135, 1, 0, 0, 0, 629, 630, 5, 43, 0, 0, 630, 137, 1, 0, 0, 0, 631, 632, 5, 45, 0, 0, 632, 139, 1, 0, 0, 0, 633, 634, 5, 42, 0, 0, 634, 141, 1, 0, 0, 0, 635, 636, 5, 47, 0, 0, 636, 143, 1, 0, 0, 0, 637, 638, 5, 37, 0, 0, 638, 145, 1, 0, 0, 0, 639, 640, 5, 91, 0, 0, 640, 641, 1, 0, 0, 0, 641, 642, 6, 71, 0, 0, 642, 643, 6, 71, 0, 0, 643, 147, 1, 0, 0, 0, 644, 645, 5, 93, 0, 0, 645, 646, 1, 0, 0, 0, 646, 647, 6, 72, 7, 0, 647, 648, 6, 72, 7, 0, 648, 149, 1, 0, 0, 0, 649, 655, 3, 62, 29, 0, 650, 654, 3, 62, 29, 0, 651, 654, 3, 60, 28, 0, 652, 654, 5, 95, 0, 0, 653, 650, 1, 0, 0, 0, 653, 651, 1, 0, 0, 0, 653, 652, 1, 0, 0, 0, 654, 657, 1, 0, 0, 0, 655, 653, 1, 0, 0, 0, 655, 656, 1, 0, 0, 0, 656, 667, 1, 0, 0, 0, 657, 655, 1, 0, 0, 0, 658, 662, 7, 9, 0, 0, 659, 663, 3, 62, 29, 0, 660, 663, 3, 60, 28, 0, 661, 663, 5, 95, 0, 0, 662, 659, 1, 0, 0, 0, 662, 660, 1, 0, 0, 0, 662, 661, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 662, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, 665, 667, 1, 0, 0, 0, 666, 649, 1, 0, 0, 0, 666, 658, 1, 0, 0, 0, 667, 151, 1, 0, 0, 0, 668, 674, 5, 96, 0, 0, 669, 673, 8, 10, 0, 0, 670, 671, 5, 96, 0, 0, 671, 673, 5, 96, 0, 0, 672, 669, 1, 0, 0, 0, 672, 670, 1, 0, 0, 0, 673, 676, 1, 0, 0, 0, 674, 672, 1, 0, 0, 0, 674, 675, 1, 0, 0, 0, 675, 677, 1, 0, 0, 0, 676, 674, 1, 0, 0, 0, 677, 678, 5, 96, 0, 0, 678, 153, 1, 0, 0, 0, 679, 680, 3, 42, 19, 0, 680, 681, 1, 0, 0, 0, 681, 682, 6, 75, 3, 0, 682, 155, 1, 0, 0, 0, 683, 684, 3, 44, 20, 0, 684, 685, 1, 0, 0, 0, 685, 686, 6, 76, 3, 0, 686, 157, 1, 0, 0, 0, 687, 688, 3, 46, 21, 0, 688, 689, 1, 0, 0, 0, 689, 690, 6, 77, 3, 0, 690, 159, 1, 0, 0, 0, 691, 692, 5, 124, 0, 0, 692, 693, 1, 0, 0, 0, 693, 694, 6, 78, 6, 0, 694, 695, 6, 78, 7, 0, 695, 161, 1, 0, 0, 0, 696, 697, 5, 91, 0, 0, 697, 698, 1, 0, 0, 0, 698, 699, 6, 79, 4, 0, 699, 700, 6, 79, 1, 0, 700, 701, 6, 79, 1, 0, 701, 163, 1, 0, 0, 0, 702, 703, 5, 93, 0, 0, 703, 704, 1, 0, 0, 0, 704, 705, 6, 80, 7, 0, 705, 706, 6, 80, 7, 0, 706, 707, 6, 80, 8, 0, 707, 165, 1, 0, 0, 0, 708, 709, 5, 44, 0, 0, 709, 710, 1, 0, 0, 0, 710, 711, 6, 81, 9, 0, 711, 167, 1, 0, 0, 0, 712, 713, 5, 61, 0, 0, 713, 714, 1, 0, 0, 0, 714, 715, 6, 82, 10, 0, 715, 169, 1, 0, 0, 0, 716, 717, 5, 97, 0, 0, 717, 718, 5, 115, 0, 0, 718, 171, 1, 0, 0, 0, 719, 720, 5, 109, 0, 0, 720, 721, 5, 101, 0, 0, 721, 722, 5, 116, 0, 0, 722, 723, 5, 97, 0, 0, 723, 724, 5, 100, 0, 0, 724, 725, 5, 97, 0, 0, 725, 726, 5, 116, 0, 0, 726, 727, 5, 97, 0, 0, 727, 173, 1, 0, 0, 0, 728, 729, 5, 111, 0, 0, 729, 730, 5, 110, 0, 0, 730, 175, 1, 0, 0, 0, 731, 732, 5, 119, 0, 0, 732, 733, 5, 105, 0, 0, 733, 734, 5, 116, 0, 0, 734, 735, 5, 104, 0, 0, 735, 177, 1, 0, 0, 0, 736, 738, 3, 180, 88, 0, 737, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 737, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 179, 1, 0, 0, 0, 741, 743, 8, 11, 0, 0, 742, 741, 1, 0, 0, 0, 743, 744, 1, 0, 0, 0, 744, 742, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 749, 1, 0, 0, 0, 746, 747, 5, 47, 0, 0, 747, 749, 8, 12, 0, 0, 748, 742, 1, 0, 0, 0, 748, 746, 1, 0, 0, 0, 749, 181, 1, 0, 0, 0, 750, 751, 3, 152, 74, 0, 751, 183, 1, 0, 0, 0, 752, 753, 3, 42, 19, 0, 753, 754, 1, 0, 0, 0, 754, 755, 6, 90, 3, 0, 755, 185, 1, 0, 0, 0, 756, 757, 3, 44, 20, 0, 757, 758, 1, 0, 0, 0, 758, 759, 6, 91, 3, 0, 759, 187, 1, 0, 0, 0, 760, 761, 3, 46, 21, 0, 761, 762, 1, 0, 0, 0, 762, 763, 6, 92, 3, 0, 763, 189, 1, 0, 0, 0, 38, 0, 1, 2, 3, 346, 356, 360, 363, 372, 374, 385, 426, 431, 436, 438, 449, 457, 460, 462, 467, 472, 478, 485, 490, 496, 499, 507, 511, 653, 655, 662, 664, 666, 672, 674, 739, 744, 748, 11, 5, 2, 0, 5, 3, 0, 5, 1, 0, 0, 1, 0, 7, 65, 0, 5, 0, 0, 7, 26, 0, 4, 0, 0, 7, 66, 0, 7, 34, 0, 7, 33, 0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java index 0a006b9f8ad14..be46b6c6e1797 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java @@ -23,13 +23,13 @@ public class EsqlBaseLexer extends Lexer { WS=22, EXPLAIN_WS=23, EXPLAIN_LINE_COMMENT=24, EXPLAIN_MULTILINE_COMMENT=25, PIPE=26, STRING=27, INTEGER_LITERAL=28, DECIMAL_LITERAL=29, BY=30, AND=31, ASC=32, ASSIGN=33, COMMA=34, DESC=35, DOT=36, FALSE=37, FIRST=38, LAST=39, - LP=40, IN=41, LIKE=42, NOT=43, NULL=44, NULLS=45, OR=46, PARAM=47, RLIKE=48, - RP=49, TRUE=50, INFO=51, FUNCTIONS=52, EQ=53, NEQ=54, LT=55, LTE=56, GT=57, - GTE=58, PLUS=59, MINUS=60, ASTERISK=61, SLASH=62, PERCENT=63, OPENING_BRACKET=64, - CLOSING_BRACKET=65, UNQUOTED_IDENTIFIER=66, QUOTED_IDENTIFIER=67, EXPR_LINE_COMMENT=68, - EXPR_MULTILINE_COMMENT=69, EXPR_WS=70, AS=71, METADATA=72, ON=73, WITH=74, - SRC_UNQUOTED_IDENTIFIER=75, SRC_QUOTED_IDENTIFIER=76, SRC_LINE_COMMENT=77, - SRC_MULTILINE_COMMENT=78, SRC_WS=79, EXPLAIN_PIPE=80; + LP=40, IN=41, IS=42, LIKE=43, NOT=44, NULL=45, NULLS=46, OR=47, PARAM=48, + RLIKE=49, RP=50, TRUE=51, INFO=52, FUNCTIONS=53, EQ=54, NEQ=55, LT=56, + LTE=57, GT=58, GTE=59, PLUS=60, MINUS=61, ASTERISK=62, SLASH=63, PERCENT=64, + OPENING_BRACKET=65, CLOSING_BRACKET=66, UNQUOTED_IDENTIFIER=67, QUOTED_IDENTIFIER=68, + EXPR_LINE_COMMENT=69, EXPR_MULTILINE_COMMENT=70, EXPR_WS=71, AS=72, METADATA=73, + ON=74, WITH=75, SRC_UNQUOTED_IDENTIFIER=76, SRC_QUOTED_IDENTIFIER=77, + SRC_LINE_COMMENT=78, SRC_MULTILINE_COMMENT=79, SRC_WS=80, EXPLAIN_PIPE=81; public static final int EXPLAIN_MODE=1, EXPRESSION=2, SOURCE_IDENTIFIERS=3; public static String[] channelNames = { @@ -49,14 +49,14 @@ private static String[] makeRuleNames() { "EXPLAIN_MULTILINE_COMMENT", "PIPE", "DIGIT", "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", "COMMA", "DESC", "DOT", "FALSE", "FIRST", - "LAST", "LP", "IN", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", - "RP", "TRUE", "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", - "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", - "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", - "EXPR_WS", "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", - "SRC_COMMA", "SRC_ASSIGN", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", - "SRC_UNQUOTED_IDENTIFIER_PART", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS" + "LAST", "LP", "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", + "RLIKE", "RP", "TRUE", "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", + "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", + "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", + "EXPR_MULTILINE_COMMENT", "EXPR_WS", "SRC_PIPE", "SRC_OPENING_BRACKET", + "SRC_CLOSING_BRACKET", "SRC_COMMA", "SRC_ASSIGN", "AS", "METADATA", "ON", + "WITH", "SRC_UNQUOTED_IDENTIFIER", "SRC_UNQUOTED_IDENTIFIER_PART", "SRC_QUOTED_IDENTIFIER", + "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", "SRC_WS" }; } public static final String[] ruleNames = makeRuleNames(); @@ -68,8 +68,8 @@ private static String[] makeLiteralNames() { "'rename'", "'row'", "'show'", "'sort'", "'stats'", "'where'", null, null, null, null, null, null, null, null, null, null, null, "'by'", "'and'", "'asc'", null, null, "'desc'", "'.'", "'false'", "'first'", "'last'", - "'('", "'in'", "'like'", "'not'", "'null'", "'nulls'", "'or'", "'?'", - "'rlike'", "')'", "'true'", "'info'", "'functions'", "'=='", "'!='", + "'('", "'in'", "'is'", "'like'", "'not'", "'null'", "'nulls'", "'or'", + "'?'", "'rlike'", "')'", "'true'", "'info'", "'functions'", "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", null, "']'", null, null, null, null, null, "'as'", "'metadata'", "'on'", "'with'" }; @@ -83,9 +83,9 @@ private static String[] makeSymbolicNames() { "WS", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", - "IN", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", - "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", - "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", + "TRUE", "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", @@ -151,7 +151,7 @@ public EsqlBaseLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\u0004\u0000P\u02f7\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ + "\u0004\u0000Q\u02fc\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ "\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ @@ -174,456 +174,459 @@ public EsqlBaseLexer(CharStream input) { "K\u0007K\u0002L\u0007L\u0002M\u0007M\u0002N\u0007N\u0002O\u0007O\u0002"+ "P\u0007P\u0002Q\u0007Q\u0002R\u0007R\u0002S\u0007S\u0002T\u0007T\u0002"+ "U\u0007U\u0002V\u0007V\u0002W\u0007W\u0002X\u0007X\u0002Y\u0007Y\u0002"+ - "Z\u0007Z\u0002[\u0007[\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+ + "Z\u0007Z\u0002[\u0007[\u0002\\\u0007\\\u0001\u0000\u0001\u0000\u0001\u0000"+ "\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002"+ - "\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003"+ - "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004"+ + "\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002"+ + "\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003"+ + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ - "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005"+ - "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006"+ - "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+ + "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005"+ + "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006"+ + "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ "\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+ "\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+ - "\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\n\u0001"+ - "\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ - "\n\u0001\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ - "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001"+ - "\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\r\u0001"+ - "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000e"+ - "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f"+ - "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010"+ + "\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ + "\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ + "\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ + "\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ + "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ + "\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001"+ + "\f\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e"+ + "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000f"+ + "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f"+ "\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010"+ - "\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011"+ - "\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0004\u0012\u0157\b\u0012"+ - "\u000b\u0012\f\u0012\u0158\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013"+ - "\u0001\u0013\u0001\u0013\u0005\u0013\u0161\b\u0013\n\u0013\f\u0013\u0164"+ - "\t\u0013\u0001\u0013\u0003\u0013\u0167\b\u0013\u0001\u0013\u0003\u0013"+ - "\u016a\b\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0014"+ - "\u0001\u0014\u0001\u0014\u0005\u0014\u0173\b\u0014\n\u0014\f\u0014\u0176"+ - "\t\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001"+ - "\u0015\u0004\u0015\u017e\b\u0015\u000b\u0015\f\u0015\u017f\u0001\u0015"+ - "\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+ - "\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018"+ - "\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019"+ - "\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001b"+ - "\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d"+ - "\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+ - "\u0001 \u0001 \u0003 \u01a9\b \u0001 \u0004 \u01ac\b \u000b \f \u01ad"+ - "\u0001!\u0001!\u0001!\u0005!\u01b3\b!\n!\f!\u01b6\t!\u0001!\u0001!\u0001"+ - "!\u0001!\u0001!\u0001!\u0005!\u01be\b!\n!\f!\u01c1\t!\u0001!\u0001!\u0001"+ - "!\u0001!\u0001!\u0003!\u01c8\b!\u0001!\u0003!\u01cb\b!\u0003!\u01cd\b"+ - "!\u0001\"\u0004\"\u01d0\b\"\u000b\"\f\"\u01d1\u0001#\u0004#\u01d5\b#\u000b"+ - "#\f#\u01d6\u0001#\u0001#\u0005#\u01db\b#\n#\f#\u01de\t#\u0001#\u0001#"+ - "\u0004#\u01e2\b#\u000b#\f#\u01e3\u0001#\u0004#\u01e7\b#\u000b#\f#\u01e8"+ - "\u0001#\u0001#\u0005#\u01ed\b#\n#\f#\u01f0\t#\u0003#\u01f2\b#\u0001#\u0001"+ - "#\u0001#\u0001#\u0004#\u01f8\b#\u000b#\f#\u01f9\u0001#\u0001#\u0003#\u01fe"+ - "\b#\u0001$\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0001&\u0001&\u0001"+ - "&\u0001&\u0001\'\u0001\'\u0001(\u0001(\u0001)\u0001)\u0001)\u0001)\u0001"+ - ")\u0001*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001+\u0001+\u0001,\u0001"+ - ",\u0001,\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001-\u0001"+ - ".\u0001.\u0001/\u0001/\u0001/\u00010\u00010\u00010\u00010\u00010\u0001"+ - "1\u00011\u00011\u00011\u00012\u00012\u00012\u00012\u00012\u00013\u0001"+ - "3\u00013\u00013\u00013\u00013\u00014\u00014\u00014\u00015\u00015\u0001"+ - "6\u00016\u00016\u00016\u00016\u00016\u00017\u00017\u00018\u00018\u0001"+ - "8\u00018\u00018\u00019\u00019\u00019\u00019\u00019\u0001:\u0001:\u0001"+ - ":\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001:\u0001;\u0001;\u0001"+ - ";\u0001<\u0001<\u0001<\u0001=\u0001=\u0001>\u0001>\u0001>\u0001?\u0001"+ - "?\u0001@\u0001@\u0001@\u0001A\u0001A\u0001B\u0001B\u0001C\u0001C\u0001"+ - "D\u0001D\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001F\u0001G\u0001"+ - "G\u0001G\u0001G\u0001G\u0001H\u0001H\u0001H\u0001H\u0005H\u0289\bH\nH"+ - "\fH\u028c\tH\u0001H\u0001H\u0001H\u0001H\u0004H\u0292\bH\u000bH\fH\u0293"+ - "\u0003H\u0296\bH\u0001I\u0001I\u0001I\u0001I\u0005I\u029c\bI\nI\fI\u029f"+ - "\tI\u0001I\u0001I\u0001J\u0001J\u0001J\u0001J\u0001K\u0001K\u0001K\u0001"+ - "K\u0001L\u0001L\u0001L\u0001L\u0001M\u0001M\u0001M\u0001M\u0001M\u0001"+ - "N\u0001N\u0001N\u0001N\u0001N\u0001N\u0001O\u0001O\u0001O\u0001O\u0001"+ - "O\u0001O\u0001P\u0001P\u0001P\u0001P\u0001Q\u0001Q\u0001Q\u0001Q\u0001"+ - "R\u0001R\u0001R\u0001S\u0001S\u0001S\u0001S\u0001S\u0001S\u0001S\u0001"+ - "S\u0001S\u0001T\u0001T\u0001T\u0001U\u0001U\u0001U\u0001U\u0001U\u0001"+ - "V\u0004V\u02dd\bV\u000bV\fV\u02de\u0001W\u0004W\u02e2\bW\u000bW\fW\u02e3"+ - "\u0001W\u0001W\u0003W\u02e8\bW\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0001"+ - "Y\u0001Z\u0001Z\u0001Z\u0001Z\u0001[\u0001[\u0001[\u0001[\u0002\u0174"+ - "\u01bf\u0000\\\u0004\u0001\u0006\u0002\b\u0003\n\u0004\f\u0005\u000e\u0006"+ - "\u0010\u0007\u0012\b\u0014\t\u0016\n\u0018\u000b\u001a\f\u001c\r\u001e"+ - "\u000e \u000f\"\u0010$\u0011&\u0012(\u0013*\u0014,\u0015.\u00160\u0000"+ - "2P4\u00176\u00188\u0019:\u001a<\u0000>\u0000@\u0000B\u0000D\u0000F\u001b"+ - "H\u001cJ\u001dL\u001eN\u001fP R!T\"V#X$Z%\\&^\'`(b)d*f+h,j-l.n/p0r1t2"+ - "v3x4z5|6~7\u00808\u00829\u0084:\u0086;\u0088<\u008a=\u008c>\u008e?\u0090"+ - "@\u0092A\u0094B\u0096C\u0098D\u009aE\u009cF\u009e\u0000\u00a0\u0000\u00a2"+ - "\u0000\u00a4\u0000\u00a6\u0000\u00a8G\u00aaH\u00acI\u00aeJ\u00b0K\u00b2"+ - "\u0000\u00b4L\u00b6M\u00b8N\u00baO\u0004\u0000\u0001\u0002\u0003\r\u0006"+ - "\u0000\t\n\r\r //[[]]\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r \u0001"+ - "\u000009\u0002\u0000AZaz\u0005\u0000\"\"\\\\nnrrtt\u0004\u0000\n\n\r\r"+ - "\"\"\\\\\u0002\u0000EEee\u0002\u0000++--\u0002\u0000@@__\u0001\u0000`"+ - "`\n\u0000\t\n\r\r ,,//==[[]]``||\u0002\u0000**//\u0313\u0000\u0004\u0001"+ - "\u0000\u0000\u0000\u0000\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001\u0000"+ - "\u0000\u0000\u0000\n\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000\u0000"+ - "\u0000\u0000\u000e\u0001\u0000\u0000\u0000\u0000\u0010\u0001\u0000\u0000"+ - "\u0000\u0000\u0012\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000"+ - "\u0000\u0000\u0016\u0001\u0000\u0000\u0000\u0000\u0018\u0001\u0000\u0000"+ - "\u0000\u0000\u001a\u0001\u0000\u0000\u0000\u0000\u001c\u0001\u0000\u0000"+ - "\u0000\u0000\u001e\u0001\u0000\u0000\u0000\u0000 \u0001\u0000\u0000\u0000"+ - "\u0000\"\u0001\u0000\u0000\u0000\u0000$\u0001\u0000\u0000\u0000\u0000"+ - "&\u0001\u0000\u0000\u0000\u0000(\u0001\u0000\u0000\u0000\u0000*\u0001"+ - "\u0000\u0000\u0000\u0000,\u0001\u0000\u0000\u0000\u0000.\u0001\u0000\u0000"+ - "\u0000\u00010\u0001\u0000\u0000\u0000\u00012\u0001\u0000\u0000\u0000\u0001"+ - "4\u0001\u0000\u0000\u0000\u00016\u0001\u0000\u0000\u0000\u00018\u0001"+ - "\u0000\u0000\u0000\u0002:\u0001\u0000\u0000\u0000\u0002F\u0001\u0000\u0000"+ - "\u0000\u0002H\u0001\u0000\u0000\u0000\u0002J\u0001\u0000\u0000\u0000\u0002"+ - "L\u0001\u0000\u0000\u0000\u0002N\u0001\u0000\u0000\u0000\u0002P\u0001"+ - "\u0000\u0000\u0000\u0002R\u0001\u0000\u0000\u0000\u0002T\u0001\u0000\u0000"+ - "\u0000\u0002V\u0001\u0000\u0000\u0000\u0002X\u0001\u0000\u0000\u0000\u0002"+ - "Z\u0001\u0000\u0000\u0000\u0002\\\u0001\u0000\u0000\u0000\u0002^\u0001"+ - "\u0000\u0000\u0000\u0002`\u0001\u0000\u0000\u0000\u0002b\u0001\u0000\u0000"+ - "\u0000\u0002d\u0001\u0000\u0000\u0000\u0002f\u0001\u0000\u0000\u0000\u0002"+ - "h\u0001\u0000\u0000\u0000\u0002j\u0001\u0000\u0000\u0000\u0002l\u0001"+ - "\u0000\u0000\u0000\u0002n\u0001\u0000\u0000\u0000\u0002p\u0001\u0000\u0000"+ - "\u0000\u0002r\u0001\u0000\u0000\u0000\u0002t\u0001\u0000\u0000\u0000\u0002"+ - "v\u0001\u0000\u0000\u0000\u0002x\u0001\u0000\u0000\u0000\u0002z\u0001"+ - "\u0000\u0000\u0000\u0002|\u0001\u0000\u0000\u0000\u0002~\u0001\u0000\u0000"+ - "\u0000\u0002\u0080\u0001\u0000\u0000\u0000\u0002\u0082\u0001\u0000\u0000"+ - "\u0000\u0002\u0084\u0001\u0000\u0000\u0000\u0002\u0086\u0001\u0000\u0000"+ - "\u0000\u0002\u0088\u0001\u0000\u0000\u0000\u0002\u008a\u0001\u0000\u0000"+ - "\u0000\u0002\u008c\u0001\u0000\u0000\u0000\u0002\u008e\u0001\u0000\u0000"+ - "\u0000\u0002\u0090\u0001\u0000\u0000\u0000\u0002\u0092\u0001\u0000\u0000"+ - "\u0000\u0002\u0094\u0001\u0000\u0000\u0000\u0002\u0096\u0001\u0000\u0000"+ - "\u0000\u0002\u0098\u0001\u0000\u0000\u0000\u0002\u009a\u0001\u0000\u0000"+ - "\u0000\u0002\u009c\u0001\u0000\u0000\u0000\u0003\u009e\u0001\u0000\u0000"+ - "\u0000\u0003\u00a0\u0001\u0000\u0000\u0000\u0003\u00a2\u0001\u0000\u0000"+ - "\u0000\u0003\u00a4\u0001\u0000\u0000\u0000\u0003\u00a6\u0001\u0000\u0000"+ - "\u0000\u0003\u00a8\u0001\u0000\u0000\u0000\u0003\u00aa\u0001\u0000\u0000"+ - "\u0000\u0003\u00ac\u0001\u0000\u0000\u0000\u0003\u00ae\u0001\u0000\u0000"+ - "\u0000\u0003\u00b0\u0001\u0000\u0000\u0000\u0003\u00b4\u0001\u0000\u0000"+ - "\u0000\u0003\u00b6\u0001\u0000\u0000\u0000\u0003\u00b8\u0001\u0000\u0000"+ - "\u0000\u0003\u00ba\u0001\u0000\u0000\u0000\u0004\u00bc\u0001\u0000\u0000"+ - "\u0000\u0006\u00c6\u0001\u0000\u0000\u0000\b\u00cd\u0001\u0000\u0000\u0000"+ - "\n\u00d6\u0001\u0000\u0000\u0000\f\u00dd\u0001\u0000\u0000\u0000\u000e"+ - "\u00e7\u0001\u0000\u0000\u0000\u0010\u00ee\u0001\u0000\u0000\u0000\u0012"+ - "\u00f5\u0001\u0000\u0000\u0000\u0014\u0103\u0001\u0000\u0000\u0000\u0016"+ - "\u010a\u0001\u0000\u0000\u0000\u0018\u0112\u0001\u0000\u0000\u0000\u001a"+ - "\u011e\u0001\u0000\u0000\u0000\u001c\u0128\u0001\u0000\u0000\u0000\u001e"+ - "\u0131\u0001\u0000\u0000\u0000 \u0137\u0001\u0000\u0000\u0000\"\u013e"+ - "\u0001\u0000\u0000\u0000$\u0145\u0001\u0000\u0000\u0000&\u014d\u0001\u0000"+ - "\u0000\u0000(\u0156\u0001\u0000\u0000\u0000*\u015c\u0001\u0000\u0000\u0000"+ - ",\u016d\u0001\u0000\u0000\u0000.\u017d\u0001\u0000\u0000\u00000\u0183"+ - "\u0001\u0000\u0000\u00002\u0188\u0001\u0000\u0000\u00004\u018d\u0001\u0000"+ - "\u0000\u00006\u0191\u0001\u0000\u0000\u00008\u0195\u0001\u0000\u0000\u0000"+ - ":\u0199\u0001\u0000\u0000\u0000<\u019d\u0001\u0000\u0000\u0000>\u019f"+ - "\u0001\u0000\u0000\u0000@\u01a1\u0001\u0000\u0000\u0000B\u01a4\u0001\u0000"+ - "\u0000\u0000D\u01a6\u0001\u0000\u0000\u0000F\u01cc\u0001\u0000\u0000\u0000"+ - "H\u01cf\u0001\u0000\u0000\u0000J\u01fd\u0001\u0000\u0000\u0000L\u01ff"+ - "\u0001\u0000\u0000\u0000N\u0202\u0001\u0000\u0000\u0000P\u0206\u0001\u0000"+ - "\u0000\u0000R\u020a\u0001\u0000\u0000\u0000T\u020c\u0001\u0000\u0000\u0000"+ - "V\u020e\u0001\u0000\u0000\u0000X\u0213\u0001\u0000\u0000\u0000Z\u0215"+ - "\u0001\u0000\u0000\u0000\\\u021b\u0001\u0000\u0000\u0000^\u0221\u0001"+ - "\u0000\u0000\u0000`\u0226\u0001\u0000\u0000\u0000b\u0228\u0001\u0000\u0000"+ - "\u0000d\u022b\u0001\u0000\u0000\u0000f\u0230\u0001\u0000\u0000\u0000h"+ - "\u0234\u0001\u0000\u0000\u0000j\u0239\u0001\u0000\u0000\u0000l\u023f\u0001"+ - "\u0000\u0000\u0000n\u0242\u0001\u0000\u0000\u0000p\u0244\u0001\u0000\u0000"+ - "\u0000r\u024a\u0001\u0000\u0000\u0000t\u024c\u0001\u0000\u0000\u0000v"+ - "\u0251\u0001\u0000\u0000\u0000x\u0256\u0001\u0000\u0000\u0000z\u0260\u0001"+ - "\u0000\u0000\u0000|\u0263\u0001\u0000\u0000\u0000~\u0266\u0001\u0000\u0000"+ - "\u0000\u0080\u0268\u0001\u0000\u0000\u0000\u0082\u026b\u0001\u0000\u0000"+ - "\u0000\u0084\u026d\u0001\u0000\u0000\u0000\u0086\u0270\u0001\u0000\u0000"+ - "\u0000\u0088\u0272\u0001\u0000\u0000\u0000\u008a\u0274\u0001\u0000\u0000"+ - "\u0000\u008c\u0276\u0001\u0000\u0000\u0000\u008e\u0278\u0001\u0000\u0000"+ - "\u0000\u0090\u027a\u0001\u0000\u0000\u0000\u0092\u027f\u0001\u0000\u0000"+ - "\u0000\u0094\u0295\u0001\u0000\u0000\u0000\u0096\u0297\u0001\u0000\u0000"+ - "\u0000\u0098\u02a2\u0001\u0000\u0000\u0000\u009a\u02a6\u0001\u0000\u0000"+ - "\u0000\u009c\u02aa\u0001\u0000\u0000\u0000\u009e\u02ae\u0001\u0000\u0000"+ - "\u0000\u00a0\u02b3\u0001\u0000\u0000\u0000\u00a2\u02b9\u0001\u0000\u0000"+ - "\u0000\u00a4\u02bf\u0001\u0000\u0000\u0000\u00a6\u02c3\u0001\u0000\u0000"+ - "\u0000\u00a8\u02c7\u0001\u0000\u0000\u0000\u00aa\u02ca\u0001\u0000\u0000"+ - "\u0000\u00ac\u02d3\u0001\u0000\u0000\u0000\u00ae\u02d6\u0001\u0000\u0000"+ - "\u0000\u00b0\u02dc\u0001\u0000\u0000\u0000\u00b2\u02e7\u0001\u0000\u0000"+ - "\u0000\u00b4\u02e9\u0001\u0000\u0000\u0000\u00b6\u02eb\u0001\u0000\u0000"+ - "\u0000\u00b8\u02ef\u0001\u0000\u0000\u0000\u00ba\u02f3\u0001\u0000\u0000"+ - "\u0000\u00bc\u00bd\u0005d\u0000\u0000\u00bd\u00be\u0005i\u0000\u0000\u00be"+ - "\u00bf\u0005s\u0000\u0000\u00bf\u00c0\u0005s\u0000\u0000\u00c0\u00c1\u0005"+ - "e\u0000\u0000\u00c1\u00c2\u0005c\u0000\u0000\u00c2\u00c3\u0005t\u0000"+ - "\u0000\u00c3\u00c4\u0001\u0000\u0000\u0000\u00c4\u00c5\u0006\u0000\u0000"+ - "\u0000\u00c5\u0005\u0001\u0000\u0000\u0000\u00c6\u00c7\u0005d\u0000\u0000"+ - "\u00c7\u00c8\u0005r\u0000\u0000\u00c8\u00c9\u0005o\u0000\u0000\u00c9\u00ca"+ - "\u0005p\u0000\u0000\u00ca\u00cb\u0001\u0000\u0000\u0000\u00cb\u00cc\u0006"+ - "\u0001\u0001\u0000\u00cc\u0007\u0001\u0000\u0000\u0000\u00cd\u00ce\u0005"+ - "e\u0000\u0000\u00ce\u00cf\u0005n\u0000\u0000\u00cf\u00d0\u0005r\u0000"+ - "\u0000\u00d0\u00d1\u0005i\u0000\u0000\u00d1\u00d2\u0005c\u0000\u0000\u00d2"+ - "\u00d3\u0005h\u0000\u0000\u00d3\u00d4\u0001\u0000\u0000\u0000\u00d4\u00d5"+ - "\u0006\u0002\u0001\u0000\u00d5\t\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005"+ - "e\u0000\u0000\u00d7\u00d8\u0005v\u0000\u0000\u00d8\u00d9\u0005a\u0000"+ - "\u0000\u00d9\u00da\u0005l\u0000\u0000\u00da\u00db\u0001\u0000\u0000\u0000"+ - "\u00db\u00dc\u0006\u0003\u0000\u0000\u00dc\u000b\u0001\u0000\u0000\u0000"+ - "\u00dd\u00de\u0005e\u0000\u0000\u00de\u00df\u0005x\u0000\u0000\u00df\u00e0"+ - "\u0005p\u0000\u0000\u00e0\u00e1\u0005l\u0000\u0000\u00e1\u00e2\u0005a"+ - "\u0000\u0000\u00e2\u00e3\u0005i\u0000\u0000\u00e3\u00e4\u0005n\u0000\u0000"+ - "\u00e4\u00e5\u0001\u0000\u0000\u0000\u00e5\u00e6\u0006\u0004\u0002\u0000"+ - "\u00e6\r\u0001\u0000\u0000\u0000\u00e7\u00e8\u0005f\u0000\u0000\u00e8"+ - "\u00e9\u0005r\u0000\u0000\u00e9\u00ea\u0005o\u0000\u0000\u00ea\u00eb\u0005"+ - "m\u0000\u0000\u00eb\u00ec\u0001\u0000\u0000\u0000\u00ec\u00ed\u0006\u0005"+ - "\u0001\u0000\u00ed\u000f\u0001\u0000\u0000\u0000\u00ee\u00ef\u0005g\u0000"+ - "\u0000\u00ef\u00f0\u0005r\u0000\u0000\u00f0\u00f1\u0005o\u0000\u0000\u00f1"+ - "\u00f2\u0005k\u0000\u0000\u00f2\u00f3\u0001\u0000\u0000\u0000\u00f3\u00f4"+ - "\u0006\u0006\u0000\u0000\u00f4\u0011\u0001\u0000\u0000\u0000\u00f5\u00f6"+ - "\u0005i\u0000\u0000\u00f6\u00f7\u0005n\u0000\u0000\u00f7\u00f8\u0005l"+ - "\u0000\u0000\u00f8\u00f9\u0005i\u0000\u0000\u00f9\u00fa\u0005n\u0000\u0000"+ - "\u00fa\u00fb\u0005e\u0000\u0000\u00fb\u00fc\u0005s\u0000\u0000\u00fc\u00fd"+ - "\u0005t\u0000\u0000\u00fd\u00fe\u0005a\u0000\u0000\u00fe\u00ff\u0005t"+ - "\u0000\u0000\u00ff\u0100\u0005s\u0000\u0000\u0100\u0101\u0001\u0000\u0000"+ - "\u0000\u0101\u0102\u0006\u0007\u0000\u0000\u0102\u0013\u0001\u0000\u0000"+ - "\u0000\u0103\u0104\u0005k\u0000\u0000\u0104\u0105\u0005e\u0000\u0000\u0105"+ - "\u0106\u0005e\u0000\u0000\u0106\u0107\u0005p\u0000\u0000\u0107\u0108\u0001"+ - "\u0000\u0000\u0000\u0108\u0109\u0006\b\u0001\u0000\u0109\u0015\u0001\u0000"+ - "\u0000\u0000\u010a\u010b\u0005l\u0000\u0000\u010b\u010c\u0005i\u0000\u0000"+ - "\u010c\u010d\u0005m\u0000\u0000\u010d\u010e\u0005i\u0000\u0000\u010e\u010f"+ - "\u0005t\u0000\u0000\u010f\u0110\u0001\u0000\u0000\u0000\u0110\u0111\u0006"+ - "\t\u0000\u0000\u0111\u0017\u0001\u0000\u0000\u0000\u0112\u0113\u0005m"+ - "\u0000\u0000\u0113\u0114\u0005v\u0000\u0000\u0114\u0115\u0005_\u0000\u0000"+ - "\u0115\u0116\u0005e\u0000\u0000\u0116\u0117\u0005x\u0000\u0000\u0117\u0118"+ - "\u0005p\u0000\u0000\u0118\u0119\u0005a\u0000\u0000\u0119\u011a\u0005n"+ - "\u0000\u0000\u011a\u011b\u0005d\u0000\u0000\u011b\u011c\u0001\u0000\u0000"+ - "\u0000\u011c\u011d\u0006\n\u0001\u0000\u011d\u0019\u0001\u0000\u0000\u0000"+ - "\u011e\u011f\u0005p\u0000\u0000\u011f\u0120\u0005r\u0000\u0000\u0120\u0121"+ - "\u0005o\u0000\u0000\u0121\u0122\u0005j\u0000\u0000\u0122\u0123\u0005e"+ - "\u0000\u0000\u0123\u0124\u0005c\u0000\u0000\u0124\u0125\u0005t\u0000\u0000"+ - "\u0125\u0126\u0001\u0000\u0000\u0000\u0126\u0127\u0006\u000b\u0001\u0000"+ - "\u0127\u001b\u0001\u0000\u0000\u0000\u0128\u0129\u0005r\u0000\u0000\u0129"+ - "\u012a\u0005e\u0000\u0000\u012a\u012b\u0005n\u0000\u0000\u012b\u012c\u0005"+ - "a\u0000\u0000\u012c\u012d\u0005m\u0000\u0000\u012d\u012e\u0005e\u0000"+ - "\u0000\u012e\u012f\u0001\u0000\u0000\u0000\u012f\u0130\u0006\f\u0001\u0000"+ - "\u0130\u001d\u0001\u0000\u0000\u0000\u0131\u0132\u0005r\u0000\u0000\u0132"+ - "\u0133\u0005o\u0000\u0000\u0133\u0134\u0005w\u0000\u0000\u0134\u0135\u0001"+ - "\u0000\u0000\u0000\u0135\u0136\u0006\r\u0000\u0000\u0136\u001f\u0001\u0000"+ - "\u0000\u0000\u0137\u0138\u0005s\u0000\u0000\u0138\u0139\u0005h\u0000\u0000"+ - "\u0139\u013a\u0005o\u0000\u0000\u013a\u013b\u0005w\u0000\u0000\u013b\u013c"+ - "\u0001\u0000\u0000\u0000\u013c\u013d\u0006\u000e\u0000\u0000\u013d!\u0001"+ - "\u0000\u0000\u0000\u013e\u013f\u0005s\u0000\u0000\u013f\u0140\u0005o\u0000"+ - "\u0000\u0140\u0141\u0005r\u0000\u0000\u0141\u0142\u0005t\u0000\u0000\u0142"+ - "\u0143\u0001\u0000\u0000\u0000\u0143\u0144\u0006\u000f\u0000\u0000\u0144"+ - "#\u0001\u0000\u0000\u0000\u0145\u0146\u0005s\u0000\u0000\u0146\u0147\u0005"+ - "t\u0000\u0000\u0147\u0148\u0005a\u0000\u0000\u0148\u0149\u0005t\u0000"+ - "\u0000\u0149\u014a\u0005s\u0000\u0000\u014a\u014b\u0001\u0000\u0000\u0000"+ - "\u014b\u014c\u0006\u0010\u0000\u0000\u014c%\u0001\u0000\u0000\u0000\u014d"+ - "\u014e\u0005w\u0000\u0000\u014e\u014f\u0005h\u0000\u0000\u014f\u0150\u0005"+ - "e\u0000\u0000\u0150\u0151\u0005r\u0000\u0000\u0151\u0152\u0005e\u0000"+ - "\u0000\u0152\u0153\u0001\u0000\u0000\u0000\u0153\u0154\u0006\u0011\u0000"+ - "\u0000\u0154\'\u0001\u0000\u0000\u0000\u0155\u0157\b\u0000\u0000\u0000"+ - "\u0156\u0155\u0001\u0000\u0000\u0000\u0157\u0158\u0001\u0000\u0000\u0000"+ - "\u0158\u0156\u0001\u0000\u0000\u0000\u0158\u0159\u0001\u0000\u0000\u0000"+ - "\u0159\u015a\u0001\u0000\u0000\u0000\u015a\u015b\u0006\u0012\u0000\u0000"+ - "\u015b)\u0001\u0000\u0000\u0000\u015c\u015d\u0005/\u0000\u0000\u015d\u015e"+ - "\u0005/\u0000\u0000\u015e\u0162\u0001\u0000\u0000\u0000\u015f\u0161\b"+ - "\u0001\u0000\u0000\u0160\u015f\u0001\u0000\u0000\u0000\u0161\u0164\u0001"+ - "\u0000\u0000\u0000\u0162\u0160\u0001\u0000\u0000\u0000\u0162\u0163\u0001"+ + "\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011"+ + "\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0004\u0012"+ + "\u0159\b\u0012\u000b\u0012\f\u0012\u015a\u0001\u0012\u0001\u0012\u0001"+ + "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0005\u0013\u0163\b\u0013\n"+ + "\u0013\f\u0013\u0166\t\u0013\u0001\u0013\u0003\u0013\u0169\b\u0013\u0001"+ + "\u0013\u0003\u0013\u016c\b\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001"+ + "\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0005\u0014\u0175\b\u0014\n"+ + "\u0014\f\u0014\u0178\t\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001"+ + "\u0014\u0001\u0014\u0001\u0015\u0004\u0015\u0180\b\u0015\u000b\u0015\f"+ + "\u0015\u0181\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016"+ + "\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017"+ + "\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019"+ + "\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a"+ + "\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c"+ + "\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e"+ + "\u0001\u001f\u0001\u001f\u0001 \u0001 \u0003 \u01ab\b \u0001 \u0004 \u01ae"+ + "\b \u000b \f \u01af\u0001!\u0001!\u0001!\u0005!\u01b5\b!\n!\f!\u01b8\t"+ + "!\u0001!\u0001!\u0001!\u0001!\u0001!\u0001!\u0005!\u01c0\b!\n!\f!\u01c3"+ + "\t!\u0001!\u0001!\u0001!\u0001!\u0001!\u0003!\u01ca\b!\u0001!\u0003!\u01cd"+ + "\b!\u0003!\u01cf\b!\u0001\"\u0004\"\u01d2\b\"\u000b\"\f\"\u01d3\u0001"+ + "#\u0004#\u01d7\b#\u000b#\f#\u01d8\u0001#\u0001#\u0005#\u01dd\b#\n#\f#"+ + "\u01e0\t#\u0001#\u0001#\u0004#\u01e4\b#\u000b#\f#\u01e5\u0001#\u0004#"+ + "\u01e9\b#\u000b#\f#\u01ea\u0001#\u0001#\u0005#\u01ef\b#\n#\f#\u01f2\t"+ + "#\u0003#\u01f4\b#\u0001#\u0001#\u0001#\u0001#\u0004#\u01fa\b#\u000b#\f"+ + "#\u01fb\u0001#\u0001#\u0003#\u0200\b#\u0001$\u0001$\u0001$\u0001%\u0001"+ + "%\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001(\u0001"+ + "(\u0001)\u0001)\u0001)\u0001)\u0001)\u0001*\u0001*\u0001+\u0001+\u0001"+ + "+\u0001+\u0001+\u0001+\u0001,\u0001,\u0001,\u0001,\u0001,\u0001,\u0001"+ + "-\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001/\u0001/\u0001/\u0001"+ + "0\u00010\u00010\u00011\u00011\u00011\u00011\u00011\u00012\u00012\u0001"+ + "2\u00012\u00013\u00013\u00013\u00013\u00013\u00014\u00014\u00014\u0001"+ + "4\u00014\u00014\u00015\u00015\u00015\u00016\u00016\u00017\u00017\u0001"+ + "7\u00017\u00017\u00017\u00018\u00018\u00019\u00019\u00019\u00019\u0001"+ + "9\u0001:\u0001:\u0001:\u0001:\u0001:\u0001;\u0001;\u0001;\u0001;\u0001"+ + ";\u0001;\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001=\u0001"+ + "=\u0001=\u0001>\u0001>\u0001?\u0001?\u0001?\u0001@\u0001@\u0001A\u0001"+ + "A\u0001A\u0001B\u0001B\u0001C\u0001C\u0001D\u0001D\u0001E\u0001E\u0001"+ + "F\u0001F\u0001G\u0001G\u0001G\u0001G\u0001G\u0001H\u0001H\u0001H\u0001"+ + "H\u0001H\u0001I\u0001I\u0001I\u0001I\u0005I\u028e\bI\nI\fI\u0291\tI\u0001"+ + "I\u0001I\u0001I\u0001I\u0004I\u0297\bI\u000bI\fI\u0298\u0003I\u029b\b"+ + "I\u0001J\u0001J\u0001J\u0001J\u0005J\u02a1\bJ\nJ\fJ\u02a4\tJ\u0001J\u0001"+ + "J\u0001K\u0001K\u0001K\u0001K\u0001L\u0001L\u0001L\u0001L\u0001M\u0001"+ + "M\u0001M\u0001M\u0001N\u0001N\u0001N\u0001N\u0001N\u0001O\u0001O\u0001"+ + "O\u0001O\u0001O\u0001O\u0001P\u0001P\u0001P\u0001P\u0001P\u0001P\u0001"+ + "Q\u0001Q\u0001Q\u0001Q\u0001R\u0001R\u0001R\u0001R\u0001S\u0001S\u0001"+ + "S\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001"+ + "U\u0001U\u0001U\u0001V\u0001V\u0001V\u0001V\u0001V\u0001W\u0004W\u02e2"+ + "\bW\u000bW\fW\u02e3\u0001X\u0004X\u02e7\bX\u000bX\fX\u02e8\u0001X\u0001"+ + "X\u0003X\u02ed\bX\u0001Y\u0001Y\u0001Z\u0001Z\u0001Z\u0001Z\u0001[\u0001"+ + "[\u0001[\u0001[\u0001\\\u0001\\\u0001\\\u0001\\\u0002\u0176\u01c1\u0000"+ + "]\u0004\u0001\u0006\u0002\b\u0003\n\u0004\f\u0005\u000e\u0006\u0010\u0007"+ + "\u0012\b\u0014\t\u0016\n\u0018\u000b\u001a\f\u001c\r\u001e\u000e \u000f"+ + "\"\u0010$\u0011&\u0012(\u0013*\u0014,\u0015.\u00160\u00002Q4\u00176\u0018"+ + "8\u0019:\u001a<\u0000>\u0000@\u0000B\u0000D\u0000F\u001bH\u001cJ\u001d"+ + "L\u001eN\u001fP R!T\"V#X$Z%\\&^\'`(b)d*f+h,j-l.n/p0r1t2v3x4z5|6~7\u0080"+ + "8\u00829\u0084:\u0086;\u0088<\u008a=\u008c>\u008e?\u0090@\u0092A\u0094"+ + "B\u0096C\u0098D\u009aE\u009cF\u009eG\u00a0\u0000\u00a2\u0000\u00a4\u0000"+ + "\u00a6\u0000\u00a8\u0000\u00aaH\u00acI\u00aeJ\u00b0K\u00b2L\u00b4\u0000"+ + "\u00b6M\u00b8N\u00baO\u00bcP\u0004\u0000\u0001\u0002\u0003\r\u0006\u0000"+ + "\t\n\r\r //[[]]\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r \u0001\u0000"+ + "09\u0002\u0000AZaz\u0005\u0000\"\"\\\\nnrrtt\u0004\u0000\n\n\r\r\"\"\\"+ + "\\\u0002\u0000EEee\u0002\u0000++--\u0002\u0000@@__\u0001\u0000``\n\u0000"+ + "\t\n\r\r ,,//==[[]]``||\u0002\u0000**//\u0318\u0000\u0004\u0001\u0000"+ + "\u0000\u0000\u0000\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001\u0000\u0000"+ + "\u0000\u0000\n\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000\u0000\u0000"+ + "\u0000\u000e\u0001\u0000\u0000\u0000\u0000\u0010\u0001\u0000\u0000\u0000"+ + "\u0000\u0012\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000\u0000"+ + "\u0000\u0016\u0001\u0000\u0000\u0000\u0000\u0018\u0001\u0000\u0000\u0000"+ + "\u0000\u001a\u0001\u0000\u0000\u0000\u0000\u001c\u0001\u0000\u0000\u0000"+ + "\u0000\u001e\u0001\u0000\u0000\u0000\u0000 \u0001\u0000\u0000\u0000\u0000"+ + "\"\u0001\u0000\u0000\u0000\u0000$\u0001\u0000\u0000\u0000\u0000&\u0001"+ + "\u0000\u0000\u0000\u0000(\u0001\u0000\u0000\u0000\u0000*\u0001\u0000\u0000"+ + "\u0000\u0000,\u0001\u0000\u0000\u0000\u0000.\u0001\u0000\u0000\u0000\u0001"+ + "0\u0001\u0000\u0000\u0000\u00012\u0001\u0000\u0000\u0000\u00014\u0001"+ + "\u0000\u0000\u0000\u00016\u0001\u0000\u0000\u0000\u00018\u0001\u0000\u0000"+ + "\u0000\u0002:\u0001\u0000\u0000\u0000\u0002F\u0001\u0000\u0000\u0000\u0002"+ + "H\u0001\u0000\u0000\u0000\u0002J\u0001\u0000\u0000\u0000\u0002L\u0001"+ + "\u0000\u0000\u0000\u0002N\u0001\u0000\u0000\u0000\u0002P\u0001\u0000\u0000"+ + "\u0000\u0002R\u0001\u0000\u0000\u0000\u0002T\u0001\u0000\u0000\u0000\u0002"+ + "V\u0001\u0000\u0000\u0000\u0002X\u0001\u0000\u0000\u0000\u0002Z\u0001"+ + "\u0000\u0000\u0000\u0002\\\u0001\u0000\u0000\u0000\u0002^\u0001\u0000"+ + "\u0000\u0000\u0002`\u0001\u0000\u0000\u0000\u0002b\u0001\u0000\u0000\u0000"+ + "\u0002d\u0001\u0000\u0000\u0000\u0002f\u0001\u0000\u0000\u0000\u0002h"+ + "\u0001\u0000\u0000\u0000\u0002j\u0001\u0000\u0000\u0000\u0002l\u0001\u0000"+ + "\u0000\u0000\u0002n\u0001\u0000\u0000\u0000\u0002p\u0001\u0000\u0000\u0000"+ + "\u0002r\u0001\u0000\u0000\u0000\u0002t\u0001\u0000\u0000\u0000\u0002v"+ + "\u0001\u0000\u0000\u0000\u0002x\u0001\u0000\u0000\u0000\u0002z\u0001\u0000"+ + "\u0000\u0000\u0002|\u0001\u0000\u0000\u0000\u0002~\u0001\u0000\u0000\u0000"+ + "\u0002\u0080\u0001\u0000\u0000\u0000\u0002\u0082\u0001\u0000\u0000\u0000"+ + "\u0002\u0084\u0001\u0000\u0000\u0000\u0002\u0086\u0001\u0000\u0000\u0000"+ + "\u0002\u0088\u0001\u0000\u0000\u0000\u0002\u008a\u0001\u0000\u0000\u0000"+ + "\u0002\u008c\u0001\u0000\u0000\u0000\u0002\u008e\u0001\u0000\u0000\u0000"+ + "\u0002\u0090\u0001\u0000\u0000\u0000\u0002\u0092\u0001\u0000\u0000\u0000"+ + "\u0002\u0094\u0001\u0000\u0000\u0000\u0002\u0096\u0001\u0000\u0000\u0000"+ + "\u0002\u0098\u0001\u0000\u0000\u0000\u0002\u009a\u0001\u0000\u0000\u0000"+ + "\u0002\u009c\u0001\u0000\u0000\u0000\u0002\u009e\u0001\u0000\u0000\u0000"+ + "\u0003\u00a0\u0001\u0000\u0000\u0000\u0003\u00a2\u0001\u0000\u0000\u0000"+ + "\u0003\u00a4\u0001\u0000\u0000\u0000\u0003\u00a6\u0001\u0000\u0000\u0000"+ + "\u0003\u00a8\u0001\u0000\u0000\u0000\u0003\u00aa\u0001\u0000\u0000\u0000"+ + "\u0003\u00ac\u0001\u0000\u0000\u0000\u0003\u00ae\u0001\u0000\u0000\u0000"+ + "\u0003\u00b0\u0001\u0000\u0000\u0000\u0003\u00b2\u0001\u0000\u0000\u0000"+ + "\u0003\u00b6\u0001\u0000\u0000\u0000\u0003\u00b8\u0001\u0000\u0000\u0000"+ + "\u0003\u00ba\u0001\u0000\u0000\u0000\u0003\u00bc\u0001\u0000\u0000\u0000"+ + "\u0004\u00be\u0001\u0000\u0000\u0000\u0006\u00c8\u0001\u0000\u0000\u0000"+ + "\b\u00cf\u0001\u0000\u0000\u0000\n\u00d8\u0001\u0000\u0000\u0000\f\u00df"+ + "\u0001\u0000\u0000\u0000\u000e\u00e9\u0001\u0000\u0000\u0000\u0010\u00f0"+ + "\u0001\u0000\u0000\u0000\u0012\u00f7\u0001\u0000\u0000\u0000\u0014\u0105"+ + "\u0001\u0000\u0000\u0000\u0016\u010c\u0001\u0000\u0000\u0000\u0018\u0114"+ + "\u0001\u0000\u0000\u0000\u001a\u0120\u0001\u0000\u0000\u0000\u001c\u012a"+ + "\u0001\u0000\u0000\u0000\u001e\u0133\u0001\u0000\u0000\u0000 \u0139\u0001"+ + "\u0000\u0000\u0000\"\u0140\u0001\u0000\u0000\u0000$\u0147\u0001\u0000"+ + "\u0000\u0000&\u014f\u0001\u0000\u0000\u0000(\u0158\u0001\u0000\u0000\u0000"+ + "*\u015e\u0001\u0000\u0000\u0000,\u016f\u0001\u0000\u0000\u0000.\u017f"+ + "\u0001\u0000\u0000\u00000\u0185\u0001\u0000\u0000\u00002\u018a\u0001\u0000"+ + "\u0000\u00004\u018f\u0001\u0000\u0000\u00006\u0193\u0001\u0000\u0000\u0000"+ + "8\u0197\u0001\u0000\u0000\u0000:\u019b\u0001\u0000\u0000\u0000<\u019f"+ + "\u0001\u0000\u0000\u0000>\u01a1\u0001\u0000\u0000\u0000@\u01a3\u0001\u0000"+ + "\u0000\u0000B\u01a6\u0001\u0000\u0000\u0000D\u01a8\u0001\u0000\u0000\u0000"+ + "F\u01ce\u0001\u0000\u0000\u0000H\u01d1\u0001\u0000\u0000\u0000J\u01ff"+ + "\u0001\u0000\u0000\u0000L\u0201\u0001\u0000\u0000\u0000N\u0204\u0001\u0000"+ + "\u0000\u0000P\u0208\u0001\u0000\u0000\u0000R\u020c\u0001\u0000\u0000\u0000"+ + "T\u020e\u0001\u0000\u0000\u0000V\u0210\u0001\u0000\u0000\u0000X\u0215"+ + "\u0001\u0000\u0000\u0000Z\u0217\u0001\u0000\u0000\u0000\\\u021d\u0001"+ + "\u0000\u0000\u0000^\u0223\u0001\u0000\u0000\u0000`\u0228\u0001\u0000\u0000"+ + "\u0000b\u022a\u0001\u0000\u0000\u0000d\u022d\u0001\u0000\u0000\u0000f"+ + "\u0230\u0001\u0000\u0000\u0000h\u0235\u0001\u0000\u0000\u0000j\u0239\u0001"+ + "\u0000\u0000\u0000l\u023e\u0001\u0000\u0000\u0000n\u0244\u0001\u0000\u0000"+ + "\u0000p\u0247\u0001\u0000\u0000\u0000r\u0249\u0001\u0000\u0000\u0000t"+ + "\u024f\u0001\u0000\u0000\u0000v\u0251\u0001\u0000\u0000\u0000x\u0256\u0001"+ + "\u0000\u0000\u0000z\u025b\u0001\u0000\u0000\u0000|\u0265\u0001\u0000\u0000"+ + "\u0000~\u0268\u0001\u0000\u0000\u0000\u0080\u026b\u0001\u0000\u0000\u0000"+ + "\u0082\u026d\u0001\u0000\u0000\u0000\u0084\u0270\u0001\u0000\u0000\u0000"+ + "\u0086\u0272\u0001\u0000\u0000\u0000\u0088\u0275\u0001\u0000\u0000\u0000"+ + "\u008a\u0277\u0001\u0000\u0000\u0000\u008c\u0279\u0001\u0000\u0000\u0000"+ + "\u008e\u027b\u0001\u0000\u0000\u0000\u0090\u027d\u0001\u0000\u0000\u0000"+ + "\u0092\u027f\u0001\u0000\u0000\u0000\u0094\u0284\u0001\u0000\u0000\u0000"+ + "\u0096\u029a\u0001\u0000\u0000\u0000\u0098\u029c\u0001\u0000\u0000\u0000"+ + "\u009a\u02a7\u0001\u0000\u0000\u0000\u009c\u02ab\u0001\u0000\u0000\u0000"+ + "\u009e\u02af\u0001\u0000\u0000\u0000\u00a0\u02b3\u0001\u0000\u0000\u0000"+ + "\u00a2\u02b8\u0001\u0000\u0000\u0000\u00a4\u02be\u0001\u0000\u0000\u0000"+ + "\u00a6\u02c4\u0001\u0000\u0000\u0000\u00a8\u02c8\u0001\u0000\u0000\u0000"+ + "\u00aa\u02cc\u0001\u0000\u0000\u0000\u00ac\u02cf\u0001\u0000\u0000\u0000"+ + "\u00ae\u02d8\u0001\u0000\u0000\u0000\u00b0\u02db\u0001\u0000\u0000\u0000"+ + "\u00b2\u02e1\u0001\u0000\u0000\u0000\u00b4\u02ec\u0001\u0000\u0000\u0000"+ + "\u00b6\u02ee\u0001\u0000\u0000\u0000\u00b8\u02f0\u0001\u0000\u0000\u0000"+ + "\u00ba\u02f4\u0001\u0000\u0000\u0000\u00bc\u02f8\u0001\u0000\u0000\u0000"+ + "\u00be\u00bf\u0005d\u0000\u0000\u00bf\u00c0\u0005i\u0000\u0000\u00c0\u00c1"+ + "\u0005s\u0000\u0000\u00c1\u00c2\u0005s\u0000\u0000\u00c2\u00c3\u0005e"+ + "\u0000\u0000\u00c3\u00c4\u0005c\u0000\u0000\u00c4\u00c5\u0005t\u0000\u0000"+ + "\u00c5\u00c6\u0001\u0000\u0000\u0000\u00c6\u00c7\u0006\u0000\u0000\u0000"+ + "\u00c7\u0005\u0001\u0000\u0000\u0000\u00c8\u00c9\u0005d\u0000\u0000\u00c9"+ + "\u00ca\u0005r\u0000\u0000\u00ca\u00cb\u0005o\u0000\u0000\u00cb\u00cc\u0005"+ + "p\u0000\u0000\u00cc\u00cd\u0001\u0000\u0000\u0000\u00cd\u00ce\u0006\u0001"+ + "\u0001\u0000\u00ce\u0007\u0001\u0000\u0000\u0000\u00cf\u00d0\u0005e\u0000"+ + "\u0000\u00d0\u00d1\u0005n\u0000\u0000\u00d1\u00d2\u0005r\u0000\u0000\u00d2"+ + "\u00d3\u0005i\u0000\u0000\u00d3\u00d4\u0005c\u0000\u0000\u00d4\u00d5\u0005"+ + "h\u0000\u0000\u00d5\u00d6\u0001\u0000\u0000\u0000\u00d6\u00d7\u0006\u0002"+ + "\u0001\u0000\u00d7\t\u0001\u0000\u0000\u0000\u00d8\u00d9\u0005e\u0000"+ + "\u0000\u00d9\u00da\u0005v\u0000\u0000\u00da\u00db\u0005a\u0000\u0000\u00db"+ + "\u00dc\u0005l\u0000\u0000\u00dc\u00dd\u0001\u0000\u0000\u0000\u00dd\u00de"+ + "\u0006\u0003\u0000\u0000\u00de\u000b\u0001\u0000\u0000\u0000\u00df\u00e0"+ + "\u0005e\u0000\u0000\u00e0\u00e1\u0005x\u0000\u0000\u00e1\u00e2\u0005p"+ + "\u0000\u0000\u00e2\u00e3\u0005l\u0000\u0000\u00e3\u00e4\u0005a\u0000\u0000"+ + "\u00e4\u00e5\u0005i\u0000\u0000\u00e5\u00e6\u0005n\u0000\u0000\u00e6\u00e7"+ + "\u0001\u0000\u0000\u0000\u00e7\u00e8\u0006\u0004\u0002\u0000\u00e8\r\u0001"+ + "\u0000\u0000\u0000\u00e9\u00ea\u0005f\u0000\u0000\u00ea\u00eb\u0005r\u0000"+ + "\u0000\u00eb\u00ec\u0005o\u0000\u0000\u00ec\u00ed\u0005m\u0000\u0000\u00ed"+ + "\u00ee\u0001\u0000\u0000\u0000\u00ee\u00ef\u0006\u0005\u0001\u0000\u00ef"+ + "\u000f\u0001\u0000\u0000\u0000\u00f0\u00f1\u0005g\u0000\u0000\u00f1\u00f2"+ + "\u0005r\u0000\u0000\u00f2\u00f3\u0005o\u0000\u0000\u00f3\u00f4\u0005k"+ + "\u0000\u0000\u00f4\u00f5\u0001\u0000\u0000\u0000\u00f5\u00f6\u0006\u0006"+ + "\u0000\u0000\u00f6\u0011\u0001\u0000\u0000\u0000\u00f7\u00f8\u0005i\u0000"+ + "\u0000\u00f8\u00f9\u0005n\u0000\u0000\u00f9\u00fa\u0005l\u0000\u0000\u00fa"+ + "\u00fb\u0005i\u0000\u0000\u00fb\u00fc\u0005n\u0000\u0000\u00fc\u00fd\u0005"+ + "e\u0000\u0000\u00fd\u00fe\u0005s\u0000\u0000\u00fe\u00ff\u0005t\u0000"+ + "\u0000\u00ff\u0100\u0005a\u0000\u0000\u0100\u0101\u0005t\u0000\u0000\u0101"+ + "\u0102\u0005s\u0000\u0000\u0102\u0103\u0001\u0000\u0000\u0000\u0103\u0104"+ + "\u0006\u0007\u0000\u0000\u0104\u0013\u0001\u0000\u0000\u0000\u0105\u0106"+ + "\u0005k\u0000\u0000\u0106\u0107\u0005e\u0000\u0000\u0107\u0108\u0005e"+ + "\u0000\u0000\u0108\u0109\u0005p\u0000\u0000\u0109\u010a\u0001\u0000\u0000"+ + "\u0000\u010a\u010b\u0006\b\u0001\u0000\u010b\u0015\u0001\u0000\u0000\u0000"+ + "\u010c\u010d\u0005l\u0000\u0000\u010d\u010e\u0005i\u0000\u0000\u010e\u010f"+ + "\u0005m\u0000\u0000\u010f\u0110\u0005i\u0000\u0000\u0110\u0111\u0005t"+ + "\u0000\u0000\u0111\u0112\u0001\u0000\u0000\u0000\u0112\u0113\u0006\t\u0000"+ + "\u0000\u0113\u0017\u0001\u0000\u0000\u0000\u0114\u0115\u0005m\u0000\u0000"+ + "\u0115\u0116\u0005v\u0000\u0000\u0116\u0117\u0005_\u0000\u0000\u0117\u0118"+ + "\u0005e\u0000\u0000\u0118\u0119\u0005x\u0000\u0000\u0119\u011a\u0005p"+ + "\u0000\u0000\u011a\u011b\u0005a\u0000\u0000\u011b\u011c\u0005n\u0000\u0000"+ + "\u011c\u011d\u0005d\u0000\u0000\u011d\u011e\u0001\u0000\u0000\u0000\u011e"+ + "\u011f\u0006\n\u0001\u0000\u011f\u0019\u0001\u0000\u0000\u0000\u0120\u0121"+ + "\u0005p\u0000\u0000\u0121\u0122\u0005r\u0000\u0000\u0122\u0123\u0005o"+ + "\u0000\u0000\u0123\u0124\u0005j\u0000\u0000\u0124\u0125\u0005e\u0000\u0000"+ + "\u0125\u0126\u0005c\u0000\u0000\u0126\u0127\u0005t\u0000\u0000\u0127\u0128"+ + "\u0001\u0000\u0000\u0000\u0128\u0129\u0006\u000b\u0001\u0000\u0129\u001b"+ + "\u0001\u0000\u0000\u0000\u012a\u012b\u0005r\u0000\u0000\u012b\u012c\u0005"+ + "e\u0000\u0000\u012c\u012d\u0005n\u0000\u0000\u012d\u012e\u0005a\u0000"+ + "\u0000\u012e\u012f\u0005m\u0000\u0000\u012f\u0130\u0005e\u0000\u0000\u0130"+ + "\u0131\u0001\u0000\u0000\u0000\u0131\u0132\u0006\f\u0001\u0000\u0132\u001d"+ + "\u0001\u0000\u0000\u0000\u0133\u0134\u0005r\u0000\u0000\u0134\u0135\u0005"+ + "o\u0000\u0000\u0135\u0136\u0005w\u0000\u0000\u0136\u0137\u0001\u0000\u0000"+ + "\u0000\u0137\u0138\u0006\r\u0000\u0000\u0138\u001f\u0001\u0000\u0000\u0000"+ + "\u0139\u013a\u0005s\u0000\u0000\u013a\u013b\u0005h\u0000\u0000\u013b\u013c"+ + "\u0005o\u0000\u0000\u013c\u013d\u0005w\u0000\u0000\u013d\u013e\u0001\u0000"+ + "\u0000\u0000\u013e\u013f\u0006\u000e\u0000\u0000\u013f!\u0001\u0000\u0000"+ + "\u0000\u0140\u0141\u0005s\u0000\u0000\u0141\u0142\u0005o\u0000\u0000\u0142"+ + "\u0143\u0005r\u0000\u0000\u0143\u0144\u0005t\u0000\u0000\u0144\u0145\u0001"+ + "\u0000\u0000\u0000\u0145\u0146\u0006\u000f\u0000\u0000\u0146#\u0001\u0000"+ + "\u0000\u0000\u0147\u0148\u0005s\u0000\u0000\u0148\u0149\u0005t\u0000\u0000"+ + "\u0149\u014a\u0005a\u0000\u0000\u014a\u014b\u0005t\u0000\u0000\u014b\u014c"+ + "\u0005s\u0000\u0000\u014c\u014d\u0001\u0000\u0000\u0000\u014d\u014e\u0006"+ + "\u0010\u0000\u0000\u014e%\u0001\u0000\u0000\u0000\u014f\u0150\u0005w\u0000"+ + "\u0000\u0150\u0151\u0005h\u0000\u0000\u0151\u0152\u0005e\u0000\u0000\u0152"+ + "\u0153\u0005r\u0000\u0000\u0153\u0154\u0005e\u0000\u0000\u0154\u0155\u0001"+ + "\u0000\u0000\u0000\u0155\u0156\u0006\u0011\u0000\u0000\u0156\'\u0001\u0000"+ + "\u0000\u0000\u0157\u0159\b\u0000\u0000\u0000\u0158\u0157\u0001\u0000\u0000"+ + "\u0000\u0159\u015a\u0001\u0000\u0000\u0000\u015a\u0158\u0001\u0000\u0000"+ + "\u0000\u015a\u015b\u0001\u0000\u0000\u0000\u015b\u015c\u0001\u0000\u0000"+ + "\u0000\u015c\u015d\u0006\u0012\u0000\u0000\u015d)\u0001\u0000\u0000\u0000"+ + "\u015e\u015f\u0005/\u0000\u0000\u015f\u0160\u0005/\u0000\u0000\u0160\u0164"+ + "\u0001\u0000\u0000\u0000\u0161\u0163\b\u0001\u0000\u0000\u0162\u0161\u0001"+ "\u0000\u0000\u0000\u0163\u0166\u0001\u0000\u0000\u0000\u0164\u0162\u0001"+ - "\u0000\u0000\u0000\u0165\u0167\u0005\r\u0000\u0000\u0166\u0165\u0001\u0000"+ - "\u0000\u0000\u0166\u0167\u0001\u0000\u0000\u0000\u0167\u0169\u0001\u0000"+ - "\u0000\u0000\u0168\u016a\u0005\n\u0000\u0000\u0169\u0168\u0001\u0000\u0000"+ - "\u0000\u0169\u016a\u0001\u0000\u0000\u0000\u016a\u016b\u0001\u0000\u0000"+ - "\u0000\u016b\u016c\u0006\u0013\u0003\u0000\u016c+\u0001\u0000\u0000\u0000"+ - "\u016d\u016e\u0005/\u0000\u0000\u016e\u016f\u0005*\u0000\u0000\u016f\u0174"+ - "\u0001\u0000\u0000\u0000\u0170\u0173\u0003,\u0014\u0000\u0171\u0173\t"+ - "\u0000\u0000\u0000\u0172\u0170\u0001\u0000\u0000\u0000\u0172\u0171\u0001"+ - "\u0000\u0000\u0000\u0173\u0176\u0001\u0000\u0000\u0000\u0174\u0175\u0001"+ - "\u0000\u0000\u0000\u0174\u0172\u0001\u0000\u0000\u0000\u0175\u0177\u0001"+ - "\u0000\u0000\u0000\u0176\u0174\u0001\u0000\u0000\u0000\u0177\u0178\u0005"+ - "*\u0000\u0000\u0178\u0179\u0005/\u0000\u0000\u0179\u017a\u0001\u0000\u0000"+ - "\u0000\u017a\u017b\u0006\u0014\u0003\u0000\u017b-\u0001\u0000\u0000\u0000"+ - "\u017c\u017e\u0007\u0002\u0000\u0000\u017d\u017c\u0001\u0000\u0000\u0000"+ - "\u017e\u017f\u0001\u0000\u0000\u0000\u017f\u017d\u0001\u0000\u0000\u0000"+ - "\u017f\u0180\u0001\u0000\u0000\u0000\u0180\u0181\u0001\u0000\u0000\u0000"+ - "\u0181\u0182\u0006\u0015\u0003\u0000\u0182/\u0001\u0000\u0000\u0000\u0183"+ - "\u0184\u0005[\u0000\u0000\u0184\u0185\u0001\u0000\u0000\u0000\u0185\u0186"+ - "\u0006\u0016\u0004\u0000\u0186\u0187\u0006\u0016\u0005\u0000\u01871\u0001"+ - "\u0000\u0000\u0000\u0188\u0189\u0005|\u0000\u0000\u0189\u018a\u0001\u0000"+ - "\u0000\u0000\u018a\u018b\u0006\u0017\u0006\u0000\u018b\u018c\u0006\u0017"+ - "\u0007\u0000\u018c3\u0001\u0000\u0000\u0000\u018d\u018e\u0003.\u0015\u0000"+ - "\u018e\u018f\u0001\u0000\u0000\u0000\u018f\u0190\u0006\u0018\u0003\u0000"+ - "\u01905\u0001\u0000\u0000\u0000\u0191\u0192\u0003*\u0013\u0000\u0192\u0193"+ - "\u0001\u0000\u0000\u0000\u0193\u0194\u0006\u0019\u0003\u0000\u01947\u0001"+ - "\u0000\u0000\u0000\u0195\u0196\u0003,\u0014\u0000\u0196\u0197\u0001\u0000"+ - "\u0000\u0000\u0197\u0198\u0006\u001a\u0003\u0000\u01989\u0001\u0000\u0000"+ - "\u0000\u0199\u019a\u0005|\u0000\u0000\u019a\u019b\u0001\u0000\u0000\u0000"+ - "\u019b\u019c\u0006\u001b\u0007\u0000\u019c;\u0001\u0000\u0000\u0000\u019d"+ - "\u019e\u0007\u0003\u0000\u0000\u019e=\u0001\u0000\u0000\u0000\u019f\u01a0"+ - "\u0007\u0004\u0000\u0000\u01a0?\u0001\u0000\u0000\u0000\u01a1\u01a2\u0005"+ - "\\\u0000\u0000\u01a2\u01a3\u0007\u0005\u0000\u0000\u01a3A\u0001\u0000"+ - "\u0000\u0000\u01a4\u01a5\b\u0006\u0000\u0000\u01a5C\u0001\u0000\u0000"+ - "\u0000\u01a6\u01a8\u0007\u0007\u0000\u0000\u01a7\u01a9\u0007\b\u0000\u0000"+ - "\u01a8\u01a7\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001\u0000\u0000\u0000"+ - "\u01a9\u01ab\u0001\u0000\u0000\u0000\u01aa\u01ac\u0003<\u001c\u0000\u01ab"+ - "\u01aa\u0001\u0000\u0000\u0000\u01ac\u01ad\u0001\u0000\u0000\u0000\u01ad"+ - "\u01ab\u0001\u0000\u0000\u0000\u01ad\u01ae\u0001\u0000\u0000\u0000\u01ae"+ - "E\u0001\u0000\u0000\u0000\u01af\u01b4\u0005\"\u0000\u0000\u01b0\u01b3"+ - "\u0003@\u001e\u0000\u01b1\u01b3\u0003B\u001f\u0000\u01b2\u01b0\u0001\u0000"+ - "\u0000\u0000\u01b2\u01b1\u0001\u0000\u0000\u0000\u01b3\u01b6\u0001\u0000"+ - "\u0000\u0000\u01b4\u01b2\u0001\u0000\u0000\u0000\u01b4\u01b5\u0001\u0000"+ - "\u0000\u0000\u01b5\u01b7\u0001\u0000\u0000\u0000\u01b6\u01b4\u0001\u0000"+ - "\u0000\u0000\u01b7\u01cd\u0005\"\u0000\u0000\u01b8\u01b9\u0005\"\u0000"+ - "\u0000\u01b9\u01ba\u0005\"\u0000\u0000\u01ba\u01bb\u0005\"\u0000\u0000"+ - "\u01bb\u01bf\u0001\u0000\u0000\u0000\u01bc\u01be\b\u0001\u0000\u0000\u01bd"+ - "\u01bc\u0001\u0000\u0000\u0000\u01be\u01c1\u0001\u0000\u0000\u0000\u01bf"+ - "\u01c0\u0001\u0000\u0000\u0000\u01bf\u01bd\u0001\u0000\u0000\u0000\u01c0"+ - "\u01c2\u0001\u0000\u0000\u0000\u01c1\u01bf\u0001\u0000\u0000\u0000\u01c2"+ - "\u01c3\u0005\"\u0000\u0000\u01c3\u01c4\u0005\"\u0000\u0000\u01c4\u01c5"+ - "\u0005\"\u0000\u0000\u01c5\u01c7\u0001\u0000\u0000\u0000\u01c6\u01c8\u0005"+ - "\"\u0000\u0000\u01c7\u01c6\u0001\u0000\u0000\u0000\u01c7\u01c8\u0001\u0000"+ - "\u0000\u0000\u01c8\u01ca\u0001\u0000\u0000\u0000\u01c9\u01cb\u0005\"\u0000"+ - "\u0000\u01ca\u01c9\u0001\u0000\u0000\u0000\u01ca\u01cb\u0001\u0000\u0000"+ - "\u0000\u01cb\u01cd\u0001\u0000\u0000\u0000\u01cc\u01af\u0001\u0000\u0000"+ - "\u0000\u01cc\u01b8\u0001\u0000\u0000\u0000\u01cdG\u0001\u0000\u0000\u0000"+ - "\u01ce\u01d0\u0003<\u001c\u0000\u01cf\u01ce\u0001\u0000\u0000\u0000\u01d0"+ - "\u01d1\u0001\u0000\u0000\u0000\u01d1\u01cf\u0001\u0000\u0000\u0000\u01d1"+ - "\u01d2\u0001\u0000\u0000\u0000\u01d2I\u0001\u0000\u0000\u0000\u01d3\u01d5"+ - "\u0003<\u001c\u0000\u01d4\u01d3\u0001\u0000\u0000\u0000\u01d5\u01d6\u0001"+ - "\u0000\u0000\u0000\u01d6\u01d4\u0001\u0000\u0000\u0000\u01d6\u01d7\u0001"+ - "\u0000\u0000\u0000\u01d7\u01d8\u0001\u0000\u0000\u0000\u01d8\u01dc\u0003"+ - "X*\u0000\u01d9\u01db\u0003<\u001c\u0000\u01da\u01d9\u0001\u0000\u0000"+ - "\u0000\u01db\u01de\u0001\u0000\u0000\u0000\u01dc\u01da\u0001\u0000\u0000"+ - "\u0000\u01dc\u01dd\u0001\u0000\u0000\u0000\u01dd\u01fe\u0001\u0000\u0000"+ - "\u0000\u01de\u01dc\u0001\u0000\u0000\u0000\u01df\u01e1\u0003X*\u0000\u01e0"+ - "\u01e2\u0003<\u001c\u0000\u01e1\u01e0\u0001\u0000\u0000\u0000\u01e2\u01e3"+ - "\u0001\u0000\u0000\u0000\u01e3\u01e1\u0001\u0000\u0000\u0000\u01e3\u01e4"+ - "\u0001\u0000\u0000\u0000\u01e4\u01fe\u0001\u0000\u0000\u0000\u01e5\u01e7"+ - "\u0003<\u001c\u0000\u01e6\u01e5\u0001\u0000\u0000\u0000\u01e7\u01e8\u0001"+ - "\u0000\u0000\u0000\u01e8\u01e6\u0001\u0000\u0000\u0000\u01e8\u01e9\u0001"+ - "\u0000\u0000\u0000\u01e9\u01f1\u0001\u0000\u0000\u0000\u01ea\u01ee\u0003"+ - "X*\u0000\u01eb\u01ed\u0003<\u001c\u0000\u01ec\u01eb\u0001\u0000\u0000"+ - "\u0000\u01ed\u01f0\u0001\u0000\u0000\u0000\u01ee\u01ec\u0001\u0000\u0000"+ - "\u0000\u01ee\u01ef\u0001\u0000\u0000\u0000\u01ef\u01f2\u0001\u0000\u0000"+ - "\u0000\u01f0\u01ee\u0001\u0000\u0000\u0000\u01f1\u01ea\u0001\u0000\u0000"+ - "\u0000\u01f1\u01f2\u0001\u0000\u0000\u0000\u01f2\u01f3\u0001\u0000\u0000"+ - "\u0000\u01f3\u01f4\u0003D \u0000\u01f4\u01fe\u0001\u0000\u0000\u0000\u01f5"+ - "\u01f7\u0003X*\u0000\u01f6\u01f8\u0003<\u001c\u0000\u01f7\u01f6\u0001"+ - "\u0000\u0000\u0000\u01f8\u01f9\u0001\u0000\u0000\u0000\u01f9\u01f7\u0001"+ - "\u0000\u0000\u0000\u01f9\u01fa\u0001\u0000\u0000\u0000\u01fa\u01fb\u0001"+ - "\u0000\u0000\u0000\u01fb\u01fc\u0003D \u0000\u01fc\u01fe\u0001\u0000\u0000"+ - "\u0000\u01fd\u01d4\u0001\u0000\u0000\u0000\u01fd\u01df\u0001\u0000\u0000"+ - "\u0000\u01fd\u01e6\u0001\u0000\u0000\u0000\u01fd\u01f5\u0001\u0000\u0000"+ - "\u0000\u01feK\u0001\u0000\u0000\u0000\u01ff\u0200\u0005b\u0000\u0000\u0200"+ - "\u0201\u0005y\u0000\u0000\u0201M\u0001\u0000\u0000\u0000\u0202\u0203\u0005"+ - "a\u0000\u0000\u0203\u0204\u0005n\u0000\u0000\u0204\u0205\u0005d\u0000"+ - "\u0000\u0205O\u0001\u0000\u0000\u0000\u0206\u0207\u0005a\u0000\u0000\u0207"+ - "\u0208\u0005s\u0000\u0000\u0208\u0209\u0005c\u0000\u0000\u0209Q\u0001"+ - "\u0000\u0000\u0000\u020a\u020b\u0005=\u0000\u0000\u020bS\u0001\u0000\u0000"+ - "\u0000\u020c\u020d\u0005,\u0000\u0000\u020dU\u0001\u0000\u0000\u0000\u020e"+ - "\u020f\u0005d\u0000\u0000\u020f\u0210\u0005e\u0000\u0000\u0210\u0211\u0005"+ - "s\u0000\u0000\u0211\u0212\u0005c\u0000\u0000\u0212W\u0001\u0000\u0000"+ - "\u0000\u0213\u0214\u0005.\u0000\u0000\u0214Y\u0001\u0000\u0000\u0000\u0215"+ - "\u0216\u0005f\u0000\u0000\u0216\u0217\u0005a\u0000\u0000\u0217\u0218\u0005"+ - "l\u0000\u0000\u0218\u0219\u0005s\u0000\u0000\u0219\u021a\u0005e\u0000"+ - "\u0000\u021a[\u0001\u0000\u0000\u0000\u021b\u021c\u0005f\u0000\u0000\u021c"+ - "\u021d\u0005i\u0000\u0000\u021d\u021e\u0005r\u0000\u0000\u021e\u021f\u0005"+ - "s\u0000\u0000\u021f\u0220\u0005t\u0000\u0000\u0220]\u0001\u0000\u0000"+ - "\u0000\u0221\u0222\u0005l\u0000\u0000\u0222\u0223\u0005a\u0000\u0000\u0223"+ - "\u0224\u0005s\u0000\u0000\u0224\u0225\u0005t\u0000\u0000\u0225_\u0001"+ - "\u0000\u0000\u0000\u0226\u0227\u0005(\u0000\u0000\u0227a\u0001\u0000\u0000"+ - "\u0000\u0228\u0229\u0005i\u0000\u0000\u0229\u022a\u0005n\u0000\u0000\u022a"+ - "c\u0001\u0000\u0000\u0000\u022b\u022c\u0005l\u0000\u0000\u022c\u022d\u0005"+ - "i\u0000\u0000\u022d\u022e\u0005k\u0000\u0000\u022e\u022f\u0005e\u0000"+ - "\u0000\u022fe\u0001\u0000\u0000\u0000\u0230\u0231\u0005n\u0000\u0000\u0231"+ - "\u0232\u0005o\u0000\u0000\u0232\u0233\u0005t\u0000\u0000\u0233g\u0001"+ - "\u0000\u0000\u0000\u0234\u0235\u0005n\u0000\u0000\u0235\u0236\u0005u\u0000"+ - "\u0000\u0236\u0237\u0005l\u0000\u0000\u0237\u0238\u0005l\u0000\u0000\u0238"+ - "i\u0001\u0000\u0000\u0000\u0239\u023a\u0005n\u0000\u0000\u023a\u023b\u0005"+ - "u\u0000\u0000\u023b\u023c\u0005l\u0000\u0000\u023c\u023d\u0005l\u0000"+ - "\u0000\u023d\u023e\u0005s\u0000\u0000\u023ek\u0001\u0000\u0000\u0000\u023f"+ - "\u0240\u0005o\u0000\u0000\u0240\u0241\u0005r\u0000\u0000\u0241m\u0001"+ - "\u0000\u0000\u0000\u0242\u0243\u0005?\u0000\u0000\u0243o\u0001\u0000\u0000"+ - "\u0000\u0244\u0245\u0005r\u0000\u0000\u0245\u0246\u0005l\u0000\u0000\u0246"+ - "\u0247\u0005i\u0000\u0000\u0247\u0248\u0005k\u0000\u0000\u0248\u0249\u0005"+ - "e\u0000\u0000\u0249q\u0001\u0000\u0000\u0000\u024a\u024b\u0005)\u0000"+ - "\u0000\u024bs\u0001\u0000\u0000\u0000\u024c\u024d\u0005t\u0000\u0000\u024d"+ - "\u024e\u0005r\u0000\u0000\u024e\u024f\u0005u\u0000\u0000\u024f\u0250\u0005"+ - "e\u0000\u0000\u0250u\u0001\u0000\u0000\u0000\u0251\u0252\u0005i\u0000"+ - "\u0000\u0252\u0253\u0005n\u0000\u0000\u0253\u0254\u0005f\u0000\u0000\u0254"+ - "\u0255\u0005o\u0000\u0000\u0255w\u0001\u0000\u0000\u0000\u0256\u0257\u0005"+ - "f\u0000\u0000\u0257\u0258\u0005u\u0000\u0000\u0258\u0259\u0005n\u0000"+ - "\u0000\u0259\u025a\u0005c\u0000\u0000\u025a\u025b\u0005t\u0000\u0000\u025b"+ - "\u025c\u0005i\u0000\u0000\u025c\u025d\u0005o\u0000\u0000\u025d\u025e\u0005"+ - "n\u0000\u0000\u025e\u025f\u0005s\u0000\u0000\u025fy\u0001\u0000\u0000"+ - "\u0000\u0260\u0261\u0005=\u0000\u0000\u0261\u0262\u0005=\u0000\u0000\u0262"+ - "{\u0001\u0000\u0000\u0000\u0263\u0264\u0005!\u0000\u0000\u0264\u0265\u0005"+ - "=\u0000\u0000\u0265}\u0001\u0000\u0000\u0000\u0266\u0267\u0005<\u0000"+ - "\u0000\u0267\u007f\u0001\u0000\u0000\u0000\u0268\u0269\u0005<\u0000\u0000"+ - "\u0269\u026a\u0005=\u0000\u0000\u026a\u0081\u0001\u0000\u0000\u0000\u026b"+ - "\u026c\u0005>\u0000\u0000\u026c\u0083\u0001\u0000\u0000\u0000\u026d\u026e"+ - "\u0005>\u0000\u0000\u026e\u026f\u0005=\u0000\u0000\u026f\u0085\u0001\u0000"+ - "\u0000\u0000\u0270\u0271\u0005+\u0000\u0000\u0271\u0087\u0001\u0000\u0000"+ - "\u0000\u0272\u0273\u0005-\u0000\u0000\u0273\u0089\u0001\u0000\u0000\u0000"+ - "\u0274\u0275\u0005*\u0000\u0000\u0275\u008b\u0001\u0000\u0000\u0000\u0276"+ - "\u0277\u0005/\u0000\u0000\u0277\u008d\u0001\u0000\u0000\u0000\u0278\u0279"+ - "\u0005%\u0000\u0000\u0279\u008f\u0001\u0000\u0000\u0000\u027a\u027b\u0005"+ - "[\u0000\u0000\u027b\u027c\u0001\u0000\u0000\u0000\u027c\u027d\u0006F\u0000"+ - "\u0000\u027d\u027e\u0006F\u0000\u0000\u027e\u0091\u0001\u0000\u0000\u0000"+ - "\u027f\u0280\u0005]\u0000\u0000\u0280\u0281\u0001\u0000\u0000\u0000\u0281"+ - "\u0282\u0006G\u0007\u0000\u0282\u0283\u0006G\u0007\u0000\u0283\u0093\u0001"+ - "\u0000\u0000\u0000\u0284\u028a\u0003>\u001d\u0000\u0285\u0289\u0003>\u001d"+ - "\u0000\u0286\u0289\u0003<\u001c\u0000\u0287\u0289\u0005_\u0000\u0000\u0288"+ - "\u0285\u0001\u0000\u0000\u0000\u0288\u0286\u0001\u0000\u0000\u0000\u0288"+ - "\u0287\u0001\u0000\u0000\u0000\u0289\u028c\u0001\u0000\u0000\u0000\u028a"+ - "\u0288\u0001\u0000\u0000\u0000\u028a\u028b\u0001\u0000\u0000\u0000\u028b"+ - "\u0296\u0001\u0000\u0000\u0000\u028c\u028a\u0001\u0000\u0000\u0000\u028d"+ - "\u0291\u0007\t\u0000\u0000\u028e\u0292\u0003>\u001d\u0000\u028f\u0292"+ - "\u0003<\u001c\u0000\u0290\u0292\u0005_\u0000\u0000\u0291\u028e\u0001\u0000"+ - "\u0000\u0000\u0291\u028f\u0001\u0000\u0000\u0000\u0291\u0290\u0001\u0000"+ - "\u0000\u0000\u0292\u0293\u0001\u0000\u0000\u0000\u0293\u0291\u0001\u0000"+ - "\u0000\u0000\u0293\u0294\u0001\u0000\u0000\u0000\u0294\u0296\u0001\u0000"+ - "\u0000\u0000\u0295\u0284\u0001\u0000\u0000\u0000\u0295\u028d\u0001\u0000"+ - "\u0000\u0000\u0296\u0095\u0001\u0000\u0000\u0000\u0297\u029d\u0005`\u0000"+ - "\u0000\u0298\u029c\b\n\u0000\u0000\u0299\u029a\u0005`\u0000\u0000\u029a"+ - "\u029c\u0005`\u0000\u0000\u029b\u0298\u0001\u0000\u0000\u0000\u029b\u0299"+ - "\u0001\u0000\u0000\u0000\u029c\u029f\u0001\u0000\u0000\u0000\u029d\u029b"+ - "\u0001\u0000\u0000\u0000\u029d\u029e\u0001\u0000\u0000\u0000\u029e\u02a0"+ - "\u0001\u0000\u0000\u0000\u029f\u029d\u0001\u0000\u0000\u0000\u02a0\u02a1"+ - "\u0005`\u0000\u0000\u02a1\u0097\u0001\u0000\u0000\u0000\u02a2\u02a3\u0003"+ - "*\u0013\u0000\u02a3\u02a4\u0001\u0000\u0000\u0000\u02a4\u02a5\u0006J\u0003"+ - "\u0000\u02a5\u0099\u0001\u0000\u0000\u0000\u02a6\u02a7\u0003,\u0014\u0000"+ - "\u02a7\u02a8\u0001\u0000\u0000\u0000\u02a8\u02a9\u0006K\u0003\u0000\u02a9"+ - "\u009b\u0001\u0000\u0000\u0000\u02aa\u02ab\u0003.\u0015\u0000\u02ab\u02ac"+ - "\u0001\u0000\u0000\u0000\u02ac\u02ad\u0006L\u0003\u0000\u02ad\u009d\u0001"+ - "\u0000\u0000\u0000\u02ae\u02af\u0005|\u0000\u0000\u02af\u02b0\u0001\u0000"+ - "\u0000\u0000\u02b0\u02b1\u0006M\u0006\u0000\u02b1\u02b2\u0006M\u0007\u0000"+ - "\u02b2\u009f\u0001\u0000\u0000\u0000\u02b3\u02b4\u0005[\u0000\u0000\u02b4"+ - "\u02b5\u0001\u0000\u0000\u0000\u02b5\u02b6\u0006N\u0004\u0000\u02b6\u02b7"+ - "\u0006N\u0001\u0000\u02b7\u02b8\u0006N\u0001\u0000\u02b8\u00a1\u0001\u0000"+ - "\u0000\u0000\u02b9\u02ba\u0005]\u0000\u0000\u02ba\u02bb\u0001\u0000\u0000"+ - "\u0000\u02bb\u02bc\u0006O\u0007\u0000\u02bc\u02bd\u0006O\u0007\u0000\u02bd"+ - "\u02be\u0006O\b\u0000\u02be\u00a3\u0001\u0000\u0000\u0000\u02bf\u02c0"+ - "\u0005,\u0000\u0000\u02c0\u02c1\u0001\u0000\u0000\u0000\u02c1\u02c2\u0006"+ - "P\t\u0000\u02c2\u00a5\u0001\u0000\u0000\u0000\u02c3\u02c4\u0005=\u0000"+ - "\u0000\u02c4\u02c5\u0001\u0000\u0000\u0000\u02c5\u02c6\u0006Q\n\u0000"+ - "\u02c6\u00a7\u0001\u0000\u0000\u0000\u02c7\u02c8\u0005a\u0000\u0000\u02c8"+ - "\u02c9\u0005s\u0000\u0000\u02c9\u00a9\u0001\u0000\u0000\u0000\u02ca\u02cb"+ - "\u0005m\u0000\u0000\u02cb\u02cc\u0005e\u0000\u0000\u02cc\u02cd\u0005t"+ - "\u0000\u0000\u02cd\u02ce\u0005a\u0000\u0000\u02ce\u02cf\u0005d\u0000\u0000"+ - "\u02cf\u02d0\u0005a\u0000\u0000\u02d0\u02d1\u0005t\u0000\u0000\u02d1\u02d2"+ - "\u0005a\u0000\u0000\u02d2\u00ab\u0001\u0000\u0000\u0000\u02d3\u02d4\u0005"+ - "o\u0000\u0000\u02d4\u02d5\u0005n\u0000\u0000\u02d5\u00ad\u0001\u0000\u0000"+ - "\u0000\u02d6\u02d7\u0005w\u0000\u0000\u02d7\u02d8\u0005i\u0000\u0000\u02d8"+ - "\u02d9\u0005t\u0000\u0000\u02d9\u02da\u0005h\u0000\u0000\u02da\u00af\u0001"+ - "\u0000\u0000\u0000\u02db\u02dd\u0003\u00b2W\u0000\u02dc\u02db\u0001\u0000"+ - "\u0000\u0000\u02dd\u02de\u0001\u0000\u0000\u0000\u02de\u02dc\u0001\u0000"+ - "\u0000\u0000\u02de\u02df\u0001\u0000\u0000\u0000\u02df\u00b1\u0001\u0000"+ - "\u0000\u0000\u02e0\u02e2\b\u000b\u0000\u0000\u02e1\u02e0\u0001\u0000\u0000"+ - "\u0000\u02e2\u02e3\u0001\u0000\u0000\u0000\u02e3\u02e1\u0001\u0000\u0000"+ - "\u0000\u02e3\u02e4\u0001\u0000\u0000\u0000\u02e4\u02e8\u0001\u0000\u0000"+ - "\u0000\u02e5\u02e6\u0005/\u0000\u0000\u02e6\u02e8\b\f\u0000\u0000\u02e7"+ - "\u02e1\u0001\u0000\u0000\u0000\u02e7\u02e5\u0001\u0000\u0000\u0000\u02e8"+ - "\u00b3\u0001\u0000\u0000\u0000\u02e9\u02ea\u0003\u0096I\u0000\u02ea\u00b5"+ - "\u0001\u0000\u0000\u0000\u02eb\u02ec\u0003*\u0013\u0000\u02ec\u02ed\u0001"+ - "\u0000\u0000\u0000\u02ed\u02ee\u0006Y\u0003\u0000\u02ee\u00b7\u0001\u0000"+ - "\u0000\u0000\u02ef\u02f0\u0003,\u0014\u0000\u02f0\u02f1\u0001\u0000\u0000"+ - "\u0000\u02f1\u02f2\u0006Z\u0003\u0000\u02f2\u00b9\u0001\u0000\u0000\u0000"+ - "\u02f3\u02f4\u0003.\u0015\u0000\u02f4\u02f5\u0001\u0000\u0000\u0000\u02f5"+ - "\u02f6\u0006[\u0003\u0000\u02f6\u00bb\u0001\u0000\u0000\u0000&\u0000\u0001"+ - "\u0002\u0003\u0158\u0162\u0166\u0169\u0172\u0174\u017f\u01a8\u01ad\u01b2"+ - "\u01b4\u01bf\u01c7\u01ca\u01cc\u01d1\u01d6\u01dc\u01e3\u01e8\u01ee\u01f1"+ - "\u01f9\u01fd\u0288\u028a\u0291\u0293\u0295\u029b\u029d\u02de\u02e3\u02e7"+ - "\u000b\u0005\u0002\u0000\u0005\u0003\u0000\u0005\u0001\u0000\u0000\u0001"+ - "\u0000\u0007@\u0000\u0005\u0000\u0000\u0007\u001a\u0000\u0004\u0000\u0000"+ - "\u0007A\u0000\u0007\"\u0000\u0007!\u0000"; + "\u0000\u0000\u0000\u0164\u0165\u0001\u0000\u0000\u0000\u0165\u0168\u0001"+ + "\u0000\u0000\u0000\u0166\u0164\u0001\u0000\u0000\u0000\u0167\u0169\u0005"+ + "\r\u0000\u0000\u0168\u0167\u0001\u0000\u0000\u0000\u0168\u0169\u0001\u0000"+ + "\u0000\u0000\u0169\u016b\u0001\u0000\u0000\u0000\u016a\u016c\u0005\n\u0000"+ + "\u0000\u016b\u016a\u0001\u0000\u0000\u0000\u016b\u016c\u0001\u0000\u0000"+ + "\u0000\u016c\u016d\u0001\u0000\u0000\u0000\u016d\u016e\u0006\u0013\u0003"+ + "\u0000\u016e+\u0001\u0000\u0000\u0000\u016f\u0170\u0005/\u0000\u0000\u0170"+ + "\u0171\u0005*\u0000\u0000\u0171\u0176\u0001\u0000\u0000\u0000\u0172\u0175"+ + "\u0003,\u0014\u0000\u0173\u0175\t\u0000\u0000\u0000\u0174\u0172\u0001"+ + "\u0000\u0000\u0000\u0174\u0173\u0001\u0000\u0000\u0000\u0175\u0178\u0001"+ + "\u0000\u0000\u0000\u0176\u0177\u0001\u0000\u0000\u0000\u0176\u0174\u0001"+ + "\u0000\u0000\u0000\u0177\u0179\u0001\u0000\u0000\u0000\u0178\u0176\u0001"+ + "\u0000\u0000\u0000\u0179\u017a\u0005*\u0000\u0000\u017a\u017b\u0005/\u0000"+ + "\u0000\u017b\u017c\u0001\u0000\u0000\u0000\u017c\u017d\u0006\u0014\u0003"+ + "\u0000\u017d-\u0001\u0000\u0000\u0000\u017e\u0180\u0007\u0002\u0000\u0000"+ + "\u017f\u017e\u0001\u0000\u0000\u0000\u0180\u0181\u0001\u0000\u0000\u0000"+ + "\u0181\u017f\u0001\u0000\u0000\u0000\u0181\u0182\u0001\u0000\u0000\u0000"+ + "\u0182\u0183\u0001\u0000\u0000\u0000\u0183\u0184\u0006\u0015\u0003\u0000"+ + "\u0184/\u0001\u0000\u0000\u0000\u0185\u0186\u0005[\u0000\u0000\u0186\u0187"+ + "\u0001\u0000\u0000\u0000\u0187\u0188\u0006\u0016\u0004\u0000\u0188\u0189"+ + "\u0006\u0016\u0005\u0000\u01891\u0001\u0000\u0000\u0000\u018a\u018b\u0005"+ + "|\u0000\u0000\u018b\u018c\u0001\u0000\u0000\u0000\u018c\u018d\u0006\u0017"+ + "\u0006\u0000\u018d\u018e\u0006\u0017\u0007\u0000\u018e3\u0001\u0000\u0000"+ + "\u0000\u018f\u0190\u0003.\u0015\u0000\u0190\u0191\u0001\u0000\u0000\u0000"+ + "\u0191\u0192\u0006\u0018\u0003\u0000\u01925\u0001\u0000\u0000\u0000\u0193"+ + "\u0194\u0003*\u0013\u0000\u0194\u0195\u0001\u0000\u0000\u0000\u0195\u0196"+ + "\u0006\u0019\u0003\u0000\u01967\u0001\u0000\u0000\u0000\u0197\u0198\u0003"+ + ",\u0014\u0000\u0198\u0199\u0001\u0000\u0000\u0000\u0199\u019a\u0006\u001a"+ + "\u0003\u0000\u019a9\u0001\u0000\u0000\u0000\u019b\u019c\u0005|\u0000\u0000"+ + "\u019c\u019d\u0001\u0000\u0000\u0000\u019d\u019e\u0006\u001b\u0007\u0000"+ + "\u019e;\u0001\u0000\u0000\u0000\u019f\u01a0\u0007\u0003\u0000\u0000\u01a0"+ + "=\u0001\u0000\u0000\u0000\u01a1\u01a2\u0007\u0004\u0000\u0000\u01a2?\u0001"+ + "\u0000\u0000\u0000\u01a3\u01a4\u0005\\\u0000\u0000\u01a4\u01a5\u0007\u0005"+ + "\u0000\u0000\u01a5A\u0001\u0000\u0000\u0000\u01a6\u01a7\b\u0006\u0000"+ + "\u0000\u01a7C\u0001\u0000\u0000\u0000\u01a8\u01aa\u0007\u0007\u0000\u0000"+ + "\u01a9\u01ab\u0007\b\u0000\u0000\u01aa\u01a9\u0001\u0000\u0000\u0000\u01aa"+ + "\u01ab\u0001\u0000\u0000\u0000\u01ab\u01ad\u0001\u0000\u0000\u0000\u01ac"+ + "\u01ae\u0003<\u001c\u0000\u01ad\u01ac\u0001\u0000\u0000\u0000\u01ae\u01af"+ + "\u0001\u0000\u0000\u0000\u01af\u01ad\u0001\u0000\u0000\u0000\u01af\u01b0"+ + "\u0001\u0000\u0000\u0000\u01b0E\u0001\u0000\u0000\u0000\u01b1\u01b6\u0005"+ + "\"\u0000\u0000\u01b2\u01b5\u0003@\u001e\u0000\u01b3\u01b5\u0003B\u001f"+ + "\u0000\u01b4\u01b2\u0001\u0000\u0000\u0000\u01b4\u01b3\u0001\u0000\u0000"+ + "\u0000\u01b5\u01b8\u0001\u0000\u0000\u0000\u01b6\u01b4\u0001\u0000\u0000"+ + "\u0000\u01b6\u01b7\u0001\u0000\u0000\u0000\u01b7\u01b9\u0001\u0000\u0000"+ + "\u0000\u01b8\u01b6\u0001\u0000\u0000\u0000\u01b9\u01cf\u0005\"\u0000\u0000"+ + "\u01ba\u01bb\u0005\"\u0000\u0000\u01bb\u01bc\u0005\"\u0000\u0000\u01bc"+ + "\u01bd\u0005\"\u0000\u0000\u01bd\u01c1\u0001\u0000\u0000\u0000\u01be\u01c0"+ + "\b\u0001\u0000\u0000\u01bf\u01be\u0001\u0000\u0000\u0000\u01c0\u01c3\u0001"+ + "\u0000\u0000\u0000\u01c1\u01c2\u0001\u0000\u0000\u0000\u01c1\u01bf\u0001"+ + "\u0000\u0000\u0000\u01c2\u01c4\u0001\u0000\u0000\u0000\u01c3\u01c1\u0001"+ + "\u0000\u0000\u0000\u01c4\u01c5\u0005\"\u0000\u0000\u01c5\u01c6\u0005\""+ + "\u0000\u0000\u01c6\u01c7\u0005\"\u0000\u0000\u01c7\u01c9\u0001\u0000\u0000"+ + "\u0000\u01c8\u01ca\u0005\"\u0000\u0000\u01c9\u01c8\u0001\u0000\u0000\u0000"+ + "\u01c9\u01ca\u0001\u0000\u0000\u0000\u01ca\u01cc\u0001\u0000\u0000\u0000"+ + "\u01cb\u01cd\u0005\"\u0000\u0000\u01cc\u01cb\u0001\u0000\u0000\u0000\u01cc"+ + "\u01cd\u0001\u0000\u0000\u0000\u01cd\u01cf\u0001\u0000\u0000\u0000\u01ce"+ + "\u01b1\u0001\u0000\u0000\u0000\u01ce\u01ba\u0001\u0000\u0000\u0000\u01cf"+ + "G\u0001\u0000\u0000\u0000\u01d0\u01d2\u0003<\u001c\u0000\u01d1\u01d0\u0001"+ + "\u0000\u0000\u0000\u01d2\u01d3\u0001\u0000\u0000\u0000\u01d3\u01d1\u0001"+ + "\u0000\u0000\u0000\u01d3\u01d4\u0001\u0000\u0000\u0000\u01d4I\u0001\u0000"+ + "\u0000\u0000\u01d5\u01d7\u0003<\u001c\u0000\u01d6\u01d5\u0001\u0000\u0000"+ + "\u0000\u01d7\u01d8\u0001\u0000\u0000\u0000\u01d8\u01d6\u0001\u0000\u0000"+ + "\u0000\u01d8\u01d9\u0001\u0000\u0000\u0000\u01d9\u01da\u0001\u0000\u0000"+ + "\u0000\u01da\u01de\u0003X*\u0000\u01db\u01dd\u0003<\u001c\u0000\u01dc"+ + "\u01db\u0001\u0000\u0000\u0000\u01dd\u01e0\u0001\u0000\u0000\u0000\u01de"+ + "\u01dc\u0001\u0000\u0000\u0000\u01de\u01df\u0001\u0000\u0000\u0000\u01df"+ + "\u0200\u0001\u0000\u0000\u0000\u01e0\u01de\u0001\u0000\u0000\u0000\u01e1"+ + "\u01e3\u0003X*\u0000\u01e2\u01e4\u0003<\u001c\u0000\u01e3\u01e2\u0001"+ + "\u0000\u0000\u0000\u01e4\u01e5\u0001\u0000\u0000\u0000\u01e5\u01e3\u0001"+ + "\u0000\u0000\u0000\u01e5\u01e6\u0001\u0000\u0000\u0000\u01e6\u0200\u0001"+ + "\u0000\u0000\u0000\u01e7\u01e9\u0003<\u001c\u0000\u01e8\u01e7\u0001\u0000"+ + "\u0000\u0000\u01e9\u01ea\u0001\u0000\u0000\u0000\u01ea\u01e8\u0001\u0000"+ + "\u0000\u0000\u01ea\u01eb\u0001\u0000\u0000\u0000\u01eb\u01f3\u0001\u0000"+ + "\u0000\u0000\u01ec\u01f0\u0003X*\u0000\u01ed\u01ef\u0003<\u001c\u0000"+ + "\u01ee\u01ed\u0001\u0000\u0000\u0000\u01ef\u01f2\u0001\u0000\u0000\u0000"+ + "\u01f0\u01ee\u0001\u0000\u0000\u0000\u01f0\u01f1\u0001\u0000\u0000\u0000"+ + "\u01f1\u01f4\u0001\u0000\u0000\u0000\u01f2\u01f0\u0001\u0000\u0000\u0000"+ + "\u01f3\u01ec\u0001\u0000\u0000\u0000\u01f3\u01f4\u0001\u0000\u0000\u0000"+ + "\u01f4\u01f5\u0001\u0000\u0000\u0000\u01f5\u01f6\u0003D \u0000\u01f6\u0200"+ + "\u0001\u0000\u0000\u0000\u01f7\u01f9\u0003X*\u0000\u01f8\u01fa\u0003<"+ + "\u001c\u0000\u01f9\u01f8\u0001\u0000\u0000\u0000\u01fa\u01fb\u0001\u0000"+ + "\u0000\u0000\u01fb\u01f9\u0001\u0000\u0000\u0000\u01fb\u01fc\u0001\u0000"+ + "\u0000\u0000\u01fc\u01fd\u0001\u0000\u0000\u0000\u01fd\u01fe\u0003D \u0000"+ + "\u01fe\u0200\u0001\u0000\u0000\u0000\u01ff\u01d6\u0001\u0000\u0000\u0000"+ + "\u01ff\u01e1\u0001\u0000\u0000\u0000\u01ff\u01e8\u0001\u0000\u0000\u0000"+ + "\u01ff\u01f7\u0001\u0000\u0000\u0000\u0200K\u0001\u0000\u0000\u0000\u0201"+ + "\u0202\u0005b\u0000\u0000\u0202\u0203\u0005y\u0000\u0000\u0203M\u0001"+ + "\u0000\u0000\u0000\u0204\u0205\u0005a\u0000\u0000\u0205\u0206\u0005n\u0000"+ + "\u0000\u0206\u0207\u0005d\u0000\u0000\u0207O\u0001\u0000\u0000\u0000\u0208"+ + "\u0209\u0005a\u0000\u0000\u0209\u020a\u0005s\u0000\u0000\u020a\u020b\u0005"+ + "c\u0000\u0000\u020bQ\u0001\u0000\u0000\u0000\u020c\u020d\u0005=\u0000"+ + "\u0000\u020dS\u0001\u0000\u0000\u0000\u020e\u020f\u0005,\u0000\u0000\u020f"+ + "U\u0001\u0000\u0000\u0000\u0210\u0211\u0005d\u0000\u0000\u0211\u0212\u0005"+ + "e\u0000\u0000\u0212\u0213\u0005s\u0000\u0000\u0213\u0214\u0005c\u0000"+ + "\u0000\u0214W\u0001\u0000\u0000\u0000\u0215\u0216\u0005.\u0000\u0000\u0216"+ + "Y\u0001\u0000\u0000\u0000\u0217\u0218\u0005f\u0000\u0000\u0218\u0219\u0005"+ + "a\u0000\u0000\u0219\u021a\u0005l\u0000\u0000\u021a\u021b\u0005s\u0000"+ + "\u0000\u021b\u021c\u0005e\u0000\u0000\u021c[\u0001\u0000\u0000\u0000\u021d"+ + "\u021e\u0005f\u0000\u0000\u021e\u021f\u0005i\u0000\u0000\u021f\u0220\u0005"+ + "r\u0000\u0000\u0220\u0221\u0005s\u0000\u0000\u0221\u0222\u0005t\u0000"+ + "\u0000\u0222]\u0001\u0000\u0000\u0000\u0223\u0224\u0005l\u0000\u0000\u0224"+ + "\u0225\u0005a\u0000\u0000\u0225\u0226\u0005s\u0000\u0000\u0226\u0227\u0005"+ + "t\u0000\u0000\u0227_\u0001\u0000\u0000\u0000\u0228\u0229\u0005(\u0000"+ + "\u0000\u0229a\u0001\u0000\u0000\u0000\u022a\u022b\u0005i\u0000\u0000\u022b"+ + "\u022c\u0005n\u0000\u0000\u022cc\u0001\u0000\u0000\u0000\u022d\u022e\u0005"+ + "i\u0000\u0000\u022e\u022f\u0005s\u0000\u0000\u022fe\u0001\u0000\u0000"+ + "\u0000\u0230\u0231\u0005l\u0000\u0000\u0231\u0232\u0005i\u0000\u0000\u0232"+ + "\u0233\u0005k\u0000\u0000\u0233\u0234\u0005e\u0000\u0000\u0234g\u0001"+ + "\u0000\u0000\u0000\u0235\u0236\u0005n\u0000\u0000\u0236\u0237\u0005o\u0000"+ + "\u0000\u0237\u0238\u0005t\u0000\u0000\u0238i\u0001\u0000\u0000\u0000\u0239"+ + "\u023a\u0005n\u0000\u0000\u023a\u023b\u0005u\u0000\u0000\u023b\u023c\u0005"+ + "l\u0000\u0000\u023c\u023d\u0005l\u0000\u0000\u023dk\u0001\u0000\u0000"+ + "\u0000\u023e\u023f\u0005n\u0000\u0000\u023f\u0240\u0005u\u0000\u0000\u0240"+ + "\u0241\u0005l\u0000\u0000\u0241\u0242\u0005l\u0000\u0000\u0242\u0243\u0005"+ + "s\u0000\u0000\u0243m\u0001\u0000\u0000\u0000\u0244\u0245\u0005o\u0000"+ + "\u0000\u0245\u0246\u0005r\u0000\u0000\u0246o\u0001\u0000\u0000\u0000\u0247"+ + "\u0248\u0005?\u0000\u0000\u0248q\u0001\u0000\u0000\u0000\u0249\u024a\u0005"+ + "r\u0000\u0000\u024a\u024b\u0005l\u0000\u0000\u024b\u024c\u0005i\u0000"+ + "\u0000\u024c\u024d\u0005k\u0000\u0000\u024d\u024e\u0005e\u0000\u0000\u024e"+ + "s\u0001\u0000\u0000\u0000\u024f\u0250\u0005)\u0000\u0000\u0250u\u0001"+ + "\u0000\u0000\u0000\u0251\u0252\u0005t\u0000\u0000\u0252\u0253\u0005r\u0000"+ + "\u0000\u0253\u0254\u0005u\u0000\u0000\u0254\u0255\u0005e\u0000\u0000\u0255"+ + "w\u0001\u0000\u0000\u0000\u0256\u0257\u0005i\u0000\u0000\u0257\u0258\u0005"+ + "n\u0000\u0000\u0258\u0259\u0005f\u0000\u0000\u0259\u025a\u0005o\u0000"+ + "\u0000\u025ay\u0001\u0000\u0000\u0000\u025b\u025c\u0005f\u0000\u0000\u025c"+ + "\u025d\u0005u\u0000\u0000\u025d\u025e\u0005n\u0000\u0000\u025e\u025f\u0005"+ + "c\u0000\u0000\u025f\u0260\u0005t\u0000\u0000\u0260\u0261\u0005i\u0000"+ + "\u0000\u0261\u0262\u0005o\u0000\u0000\u0262\u0263\u0005n\u0000\u0000\u0263"+ + "\u0264\u0005s\u0000\u0000\u0264{\u0001\u0000\u0000\u0000\u0265\u0266\u0005"+ + "=\u0000\u0000\u0266\u0267\u0005=\u0000\u0000\u0267}\u0001\u0000\u0000"+ + "\u0000\u0268\u0269\u0005!\u0000\u0000\u0269\u026a\u0005=\u0000\u0000\u026a"+ + "\u007f\u0001\u0000\u0000\u0000\u026b\u026c\u0005<\u0000\u0000\u026c\u0081"+ + "\u0001\u0000\u0000\u0000\u026d\u026e\u0005<\u0000\u0000\u026e\u026f\u0005"+ + "=\u0000\u0000\u026f\u0083\u0001\u0000\u0000\u0000\u0270\u0271\u0005>\u0000"+ + "\u0000\u0271\u0085\u0001\u0000\u0000\u0000\u0272\u0273\u0005>\u0000\u0000"+ + "\u0273\u0274\u0005=\u0000\u0000\u0274\u0087\u0001\u0000\u0000\u0000\u0275"+ + "\u0276\u0005+\u0000\u0000\u0276\u0089\u0001\u0000\u0000\u0000\u0277\u0278"+ + "\u0005-\u0000\u0000\u0278\u008b\u0001\u0000\u0000\u0000\u0279\u027a\u0005"+ + "*\u0000\u0000\u027a\u008d\u0001\u0000\u0000\u0000\u027b\u027c\u0005/\u0000"+ + "\u0000\u027c\u008f\u0001\u0000\u0000\u0000\u027d\u027e\u0005%\u0000\u0000"+ + "\u027e\u0091\u0001\u0000\u0000\u0000\u027f\u0280\u0005[\u0000\u0000\u0280"+ + "\u0281\u0001\u0000\u0000\u0000\u0281\u0282\u0006G\u0000\u0000\u0282\u0283"+ + "\u0006G\u0000\u0000\u0283\u0093\u0001\u0000\u0000\u0000\u0284\u0285\u0005"+ + "]\u0000\u0000\u0285\u0286\u0001\u0000\u0000\u0000\u0286\u0287\u0006H\u0007"+ + "\u0000\u0287\u0288\u0006H\u0007\u0000\u0288\u0095\u0001\u0000\u0000\u0000"+ + "\u0289\u028f\u0003>\u001d\u0000\u028a\u028e\u0003>\u001d\u0000\u028b\u028e"+ + "\u0003<\u001c\u0000\u028c\u028e\u0005_\u0000\u0000\u028d\u028a\u0001\u0000"+ + "\u0000\u0000\u028d\u028b\u0001\u0000\u0000\u0000\u028d\u028c\u0001\u0000"+ + "\u0000\u0000\u028e\u0291\u0001\u0000\u0000\u0000\u028f\u028d\u0001\u0000"+ + "\u0000\u0000\u028f\u0290\u0001\u0000\u0000\u0000\u0290\u029b\u0001\u0000"+ + "\u0000\u0000\u0291\u028f\u0001\u0000\u0000\u0000\u0292\u0296\u0007\t\u0000"+ + "\u0000\u0293\u0297\u0003>\u001d\u0000\u0294\u0297\u0003<\u001c\u0000\u0295"+ + "\u0297\u0005_\u0000\u0000\u0296\u0293\u0001\u0000\u0000\u0000\u0296\u0294"+ + "\u0001\u0000\u0000\u0000\u0296\u0295\u0001\u0000\u0000\u0000\u0297\u0298"+ + "\u0001\u0000\u0000\u0000\u0298\u0296\u0001\u0000\u0000\u0000\u0298\u0299"+ + "\u0001\u0000\u0000\u0000\u0299\u029b\u0001\u0000\u0000\u0000\u029a\u0289"+ + "\u0001\u0000\u0000\u0000\u029a\u0292\u0001\u0000\u0000\u0000\u029b\u0097"+ + "\u0001\u0000\u0000\u0000\u029c\u02a2\u0005`\u0000\u0000\u029d\u02a1\b"+ + "\n\u0000\u0000\u029e\u029f\u0005`\u0000\u0000\u029f\u02a1\u0005`\u0000"+ + "\u0000\u02a0\u029d\u0001\u0000\u0000\u0000\u02a0\u029e\u0001\u0000\u0000"+ + "\u0000\u02a1\u02a4\u0001\u0000\u0000\u0000\u02a2\u02a0\u0001\u0000\u0000"+ + "\u0000\u02a2\u02a3\u0001\u0000\u0000\u0000\u02a3\u02a5\u0001\u0000\u0000"+ + "\u0000\u02a4\u02a2\u0001\u0000\u0000\u0000\u02a5\u02a6\u0005`\u0000\u0000"+ + "\u02a6\u0099\u0001\u0000\u0000\u0000\u02a7\u02a8\u0003*\u0013\u0000\u02a8"+ + "\u02a9\u0001\u0000\u0000\u0000\u02a9\u02aa\u0006K\u0003\u0000\u02aa\u009b"+ + "\u0001\u0000\u0000\u0000\u02ab\u02ac\u0003,\u0014\u0000\u02ac\u02ad\u0001"+ + "\u0000\u0000\u0000\u02ad\u02ae\u0006L\u0003\u0000\u02ae\u009d\u0001\u0000"+ + "\u0000\u0000\u02af\u02b0\u0003.\u0015\u0000\u02b0\u02b1\u0001\u0000\u0000"+ + "\u0000\u02b1\u02b2\u0006M\u0003\u0000\u02b2\u009f\u0001\u0000\u0000\u0000"+ + "\u02b3\u02b4\u0005|\u0000\u0000\u02b4\u02b5\u0001\u0000\u0000\u0000\u02b5"+ + "\u02b6\u0006N\u0006\u0000\u02b6\u02b7\u0006N\u0007\u0000\u02b7\u00a1\u0001"+ + "\u0000\u0000\u0000\u02b8\u02b9\u0005[\u0000\u0000\u02b9\u02ba\u0001\u0000"+ + "\u0000\u0000\u02ba\u02bb\u0006O\u0004\u0000\u02bb\u02bc\u0006O\u0001\u0000"+ + "\u02bc\u02bd\u0006O\u0001\u0000\u02bd\u00a3\u0001\u0000\u0000\u0000\u02be"+ + "\u02bf\u0005]\u0000\u0000\u02bf\u02c0\u0001\u0000\u0000\u0000\u02c0\u02c1"+ + "\u0006P\u0007\u0000\u02c1\u02c2\u0006P\u0007\u0000\u02c2\u02c3\u0006P"+ + "\b\u0000\u02c3\u00a5\u0001\u0000\u0000\u0000\u02c4\u02c5\u0005,\u0000"+ + "\u0000\u02c5\u02c6\u0001\u0000\u0000\u0000\u02c6\u02c7\u0006Q\t\u0000"+ + "\u02c7\u00a7\u0001\u0000\u0000\u0000\u02c8\u02c9\u0005=\u0000\u0000\u02c9"+ + "\u02ca\u0001\u0000\u0000\u0000\u02ca\u02cb\u0006R\n\u0000\u02cb\u00a9"+ + "\u0001\u0000\u0000\u0000\u02cc\u02cd\u0005a\u0000\u0000\u02cd\u02ce\u0005"+ + "s\u0000\u0000\u02ce\u00ab\u0001\u0000\u0000\u0000\u02cf\u02d0\u0005m\u0000"+ + "\u0000\u02d0\u02d1\u0005e\u0000\u0000\u02d1\u02d2\u0005t\u0000\u0000\u02d2"+ + "\u02d3\u0005a\u0000\u0000\u02d3\u02d4\u0005d\u0000\u0000\u02d4\u02d5\u0005"+ + "a\u0000\u0000\u02d5\u02d6\u0005t\u0000\u0000\u02d6\u02d7\u0005a\u0000"+ + "\u0000\u02d7\u00ad\u0001\u0000\u0000\u0000\u02d8\u02d9\u0005o\u0000\u0000"+ + "\u02d9\u02da\u0005n\u0000\u0000\u02da\u00af\u0001\u0000\u0000\u0000\u02db"+ + "\u02dc\u0005w\u0000\u0000\u02dc\u02dd\u0005i\u0000\u0000\u02dd\u02de\u0005"+ + "t\u0000\u0000\u02de\u02df\u0005h\u0000\u0000\u02df\u00b1\u0001\u0000\u0000"+ + "\u0000\u02e0\u02e2\u0003\u00b4X\u0000\u02e1\u02e0\u0001\u0000\u0000\u0000"+ + "\u02e2\u02e3\u0001\u0000\u0000\u0000\u02e3\u02e1\u0001\u0000\u0000\u0000"+ + "\u02e3\u02e4\u0001\u0000\u0000\u0000\u02e4\u00b3\u0001\u0000\u0000\u0000"+ + "\u02e5\u02e7\b\u000b\u0000\u0000\u02e6\u02e5\u0001\u0000\u0000\u0000\u02e7"+ + "\u02e8\u0001\u0000\u0000\u0000\u02e8\u02e6\u0001\u0000\u0000\u0000\u02e8"+ + "\u02e9\u0001\u0000\u0000\u0000\u02e9\u02ed\u0001\u0000\u0000\u0000\u02ea"+ + "\u02eb\u0005/\u0000\u0000\u02eb\u02ed\b\f\u0000\u0000\u02ec\u02e6\u0001"+ + "\u0000\u0000\u0000\u02ec\u02ea\u0001\u0000\u0000\u0000\u02ed\u00b5\u0001"+ + "\u0000\u0000\u0000\u02ee\u02ef\u0003\u0098J\u0000\u02ef\u00b7\u0001\u0000"+ + "\u0000\u0000\u02f0\u02f1\u0003*\u0013\u0000\u02f1\u02f2\u0001\u0000\u0000"+ + "\u0000\u02f2\u02f3\u0006Z\u0003\u0000\u02f3\u00b9\u0001\u0000\u0000\u0000"+ + "\u02f4\u02f5\u0003,\u0014\u0000\u02f5\u02f6\u0001\u0000\u0000\u0000\u02f6"+ + "\u02f7\u0006[\u0003\u0000\u02f7\u00bb\u0001\u0000\u0000\u0000\u02f8\u02f9"+ + "\u0003.\u0015\u0000\u02f9\u02fa\u0001\u0000\u0000\u0000\u02fa\u02fb\u0006"+ + "\\\u0003\u0000\u02fb\u00bd\u0001\u0000\u0000\u0000&\u0000\u0001\u0002"+ + "\u0003\u015a\u0164\u0168\u016b\u0174\u0176\u0181\u01aa\u01af\u01b4\u01b6"+ + "\u01c1\u01c9\u01cc\u01ce\u01d3\u01d8\u01de\u01e5\u01ea\u01f0\u01f3\u01fb"+ + "\u01ff\u028d\u028f\u0296\u0298\u029a\u02a0\u02a2\u02e3\u02e8\u02ec\u000b"+ + "\u0005\u0002\u0000\u0005\u0003\u0000\u0005\u0001\u0000\u0000\u0001\u0000"+ + "\u0007A\u0000\u0005\u0000\u0000\u0007\u001a\u0000\u0004\u0000\u0000\u0007"+ + "B\u0000\u0007\"\u0000\u0007!\u0000"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp index 50cadcaf1495c..349f31f7c476d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp @@ -41,6 +41,7 @@ null 'last' '(' 'in' +'is' 'like' 'not' 'null' @@ -124,6 +125,7 @@ FIRST LAST LP IN +IS LIKE NOT NULL @@ -214,4 +216,4 @@ enrichWithClause atn: -[4, 1, 80, 494, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 102, 8, 1, 10, 1, 12, 1, 105, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 111, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 126, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 138, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 145, 8, 5, 10, 5, 12, 5, 148, 9, 5, 1, 5, 1, 5, 3, 5, 152, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 160, 8, 5, 10, 5, 12, 5, 163, 9, 5, 1, 6, 1, 6, 3, 6, 167, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 174, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 179, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 186, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 192, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 200, 8, 8, 10, 8, 12, 8, 203, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 216, 8, 9, 10, 9, 12, 9, 219, 9, 9, 3, 9, 221, 8, 9, 1, 9, 1, 9, 3, 9, 225, 8, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 5, 11, 233, 8, 11, 10, 11, 12, 11, 236, 9, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 243, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 249, 8, 13, 10, 13, 12, 13, 252, 9, 13, 1, 13, 3, 13, 255, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 5, 14, 262, 8, 14, 10, 14, 12, 14, 265, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 274, 8, 16, 1, 16, 1, 16, 3, 16, 278, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 284, 8, 17, 1, 18, 1, 18, 1, 18, 5, 18, 289, 8, 18, 10, 18, 12, 18, 292, 9, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 5, 20, 299, 8, 20, 10, 20, 12, 20, 302, 9, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 319, 8, 22, 10, 22, 12, 22, 322, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 330, 8, 22, 10, 22, 12, 22, 333, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 341, 8, 22, 10, 22, 12, 22, 344, 9, 22, 1, 22, 1, 22, 3, 22, 348, 8, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 5, 24, 357, 8, 24, 10, 24, 12, 24, 360, 9, 24, 1, 25, 1, 25, 3, 25, 364, 8, 25, 1, 25, 1, 25, 3, 25, 368, 8, 25, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 374, 8, 26, 10, 26, 12, 26, 377, 9, 26, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 383, 8, 26, 10, 26, 12, 26, 386, 9, 26, 3, 26, 388, 8, 26, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27, 394, 8, 27, 10, 27, 12, 27, 397, 9, 27, 1, 28, 1, 28, 1, 28, 1, 28, 5, 28, 403, 8, 28, 10, 28, 12, 28, 406, 9, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 416, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 5, 33, 428, 8, 33, 10, 33, 12, 33, 431, 9, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 441, 8, 36, 1, 37, 3, 37, 444, 8, 37, 1, 37, 1, 37, 1, 38, 3, 38, 449, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 468, 8, 43, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 474, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 480, 8, 44, 10, 44, 12, 44, 483, 9, 44, 3, 44, 485, 8, 44, 1, 45, 1, 45, 1, 45, 3, 45, 490, 8, 45, 1, 45, 1, 45, 1, 45, 0, 3, 2, 10, 16, 46, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 0, 8, 1, 0, 59, 60, 1, 0, 61, 63, 1, 0, 75, 76, 1, 0, 66, 67, 2, 0, 32, 32, 35, 35, 1, 0, 38, 39, 2, 0, 37, 37, 50, 50, 1, 0, 53, 58, 522, 0, 92, 1, 0, 0, 0, 2, 95, 1, 0, 0, 0, 4, 110, 1, 0, 0, 0, 6, 125, 1, 0, 0, 0, 8, 127, 1, 0, 0, 0, 10, 151, 1, 0, 0, 0, 12, 178, 1, 0, 0, 0, 14, 185, 1, 0, 0, 0, 16, 191, 1, 0, 0, 0, 18, 224, 1, 0, 0, 0, 20, 226, 1, 0, 0, 0, 22, 229, 1, 0, 0, 0, 24, 242, 1, 0, 0, 0, 26, 244, 1, 0, 0, 0, 28, 256, 1, 0, 0, 0, 30, 268, 1, 0, 0, 0, 32, 271, 1, 0, 0, 0, 34, 279, 1, 0, 0, 0, 36, 285, 1, 0, 0, 0, 38, 293, 1, 0, 0, 0, 40, 295, 1, 0, 0, 0, 42, 303, 1, 0, 0, 0, 44, 347, 1, 0, 0, 0, 46, 349, 1, 0, 0, 0, 48, 352, 1, 0, 0, 0, 50, 361, 1, 0, 0, 0, 52, 387, 1, 0, 0, 0, 54, 389, 1, 0, 0, 0, 56, 398, 1, 0, 0, 0, 58, 407, 1, 0, 0, 0, 60, 411, 1, 0, 0, 0, 62, 417, 1, 0, 0, 0, 64, 421, 1, 0, 0, 0, 66, 424, 1, 0, 0, 0, 68, 432, 1, 0, 0, 0, 70, 436, 1, 0, 0, 0, 72, 440, 1, 0, 0, 0, 74, 443, 1, 0, 0, 0, 76, 448, 1, 0, 0, 0, 78, 452, 1, 0, 0, 0, 80, 454, 1, 0, 0, 0, 82, 456, 1, 0, 0, 0, 84, 459, 1, 0, 0, 0, 86, 467, 1, 0, 0, 0, 88, 469, 1, 0, 0, 0, 90, 489, 1, 0, 0, 0, 92, 93, 3, 2, 1, 0, 93, 94, 5, 0, 0, 1, 94, 1, 1, 0, 0, 0, 95, 96, 6, 1, -1, 0, 96, 97, 3, 4, 2, 0, 97, 103, 1, 0, 0, 0, 98, 99, 10, 1, 0, 0, 99, 100, 5, 26, 0, 0, 100, 102, 3, 6, 3, 0, 101, 98, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 3, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 111, 3, 82, 41, 0, 107, 111, 3, 26, 13, 0, 108, 111, 3, 20, 10, 0, 109, 111, 3, 86, 43, 0, 110, 106, 1, 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 109, 1, 0, 0, 0, 111, 5, 1, 0, 0, 0, 112, 126, 3, 30, 15, 0, 113, 126, 3, 34, 17, 0, 114, 126, 3, 46, 23, 0, 115, 126, 3, 52, 26, 0, 116, 126, 3, 48, 24, 0, 117, 126, 3, 32, 16, 0, 118, 126, 3, 8, 4, 0, 119, 126, 3, 54, 27, 0, 120, 126, 3, 56, 28, 0, 121, 126, 3, 60, 30, 0, 122, 126, 3, 62, 31, 0, 123, 126, 3, 88, 44, 0, 124, 126, 3, 64, 32, 0, 125, 112, 1, 0, 0, 0, 125, 113, 1, 0, 0, 0, 125, 114, 1, 0, 0, 0, 125, 115, 1, 0, 0, 0, 125, 116, 1, 0, 0, 0, 125, 117, 1, 0, 0, 0, 125, 118, 1, 0, 0, 0, 125, 119, 1, 0, 0, 0, 125, 120, 1, 0, 0, 0, 125, 121, 1, 0, 0, 0, 125, 122, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 125, 124, 1, 0, 0, 0, 126, 7, 1, 0, 0, 0, 127, 128, 5, 18, 0, 0, 128, 129, 3, 10, 5, 0, 129, 9, 1, 0, 0, 0, 130, 131, 6, 5, -1, 0, 131, 132, 5, 43, 0, 0, 132, 152, 3, 10, 5, 6, 133, 152, 3, 14, 7, 0, 134, 152, 3, 12, 6, 0, 135, 137, 3, 14, 7, 0, 136, 138, 5, 43, 0, 0, 137, 136, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 140, 5, 41, 0, 0, 140, 141, 5, 40, 0, 0, 141, 146, 3, 14, 7, 0, 142, 143, 5, 34, 0, 0, 143, 145, 3, 14, 7, 0, 144, 142, 1, 0, 0, 0, 145, 148, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 149, 150, 5, 49, 0, 0, 150, 152, 1, 0, 0, 0, 151, 130, 1, 0, 0, 0, 151, 133, 1, 0, 0, 0, 151, 134, 1, 0, 0, 0, 151, 135, 1, 0, 0, 0, 152, 161, 1, 0, 0, 0, 153, 154, 10, 3, 0, 0, 154, 155, 5, 31, 0, 0, 155, 160, 3, 10, 5, 4, 156, 157, 10, 2, 0, 0, 157, 158, 5, 46, 0, 0, 158, 160, 3, 10, 5, 3, 159, 153, 1, 0, 0, 0, 159, 156, 1, 0, 0, 0, 160, 163, 1, 0, 0, 0, 161, 159, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 11, 1, 0, 0, 0, 163, 161, 1, 0, 0, 0, 164, 166, 3, 14, 7, 0, 165, 167, 5, 43, 0, 0, 166, 165, 1, 0, 0, 0, 166, 167, 1, 0, 0, 0, 167, 168, 1, 0, 0, 0, 168, 169, 5, 42, 0, 0, 169, 170, 3, 78, 39, 0, 170, 179, 1, 0, 0, 0, 171, 173, 3, 14, 7, 0, 172, 174, 5, 43, 0, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 176, 5, 48, 0, 0, 176, 177, 3, 78, 39, 0, 177, 179, 1, 0, 0, 0, 178, 164, 1, 0, 0, 0, 178, 171, 1, 0, 0, 0, 179, 13, 1, 0, 0, 0, 180, 186, 3, 16, 8, 0, 181, 182, 3, 16, 8, 0, 182, 183, 3, 80, 40, 0, 183, 184, 3, 16, 8, 0, 184, 186, 1, 0, 0, 0, 185, 180, 1, 0, 0, 0, 185, 181, 1, 0, 0, 0, 186, 15, 1, 0, 0, 0, 187, 188, 6, 8, -1, 0, 188, 192, 3, 18, 9, 0, 189, 190, 7, 0, 0, 0, 190, 192, 3, 16, 8, 3, 191, 187, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 201, 1, 0, 0, 0, 193, 194, 10, 2, 0, 0, 194, 195, 7, 1, 0, 0, 195, 200, 3, 16, 8, 3, 196, 197, 10, 1, 0, 0, 197, 198, 7, 0, 0, 0, 198, 200, 3, 16, 8, 2, 199, 193, 1, 0, 0, 0, 199, 196, 1, 0, 0, 0, 200, 203, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 17, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 204, 225, 3, 44, 22, 0, 205, 225, 3, 40, 20, 0, 206, 207, 5, 40, 0, 0, 207, 208, 3, 10, 5, 0, 208, 209, 5, 49, 0, 0, 209, 225, 1, 0, 0, 0, 210, 211, 3, 42, 21, 0, 211, 220, 5, 40, 0, 0, 212, 217, 3, 10, 5, 0, 213, 214, 5, 34, 0, 0, 214, 216, 3, 10, 5, 0, 215, 213, 1, 0, 0, 0, 216, 219, 1, 0, 0, 0, 217, 215, 1, 0, 0, 0, 217, 218, 1, 0, 0, 0, 218, 221, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 220, 212, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 222, 1, 0, 0, 0, 222, 223, 5, 49, 0, 0, 223, 225, 1, 0, 0, 0, 224, 204, 1, 0, 0, 0, 224, 205, 1, 0, 0, 0, 224, 206, 1, 0, 0, 0, 224, 210, 1, 0, 0, 0, 225, 19, 1, 0, 0, 0, 226, 227, 5, 14, 0, 0, 227, 228, 3, 22, 11, 0, 228, 21, 1, 0, 0, 0, 229, 234, 3, 24, 12, 0, 230, 231, 5, 34, 0, 0, 231, 233, 3, 24, 12, 0, 232, 230, 1, 0, 0, 0, 233, 236, 1, 0, 0, 0, 234, 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 23, 1, 0, 0, 0, 236, 234, 1, 0, 0, 0, 237, 243, 3, 10, 5, 0, 238, 239, 3, 40, 20, 0, 239, 240, 5, 33, 0, 0, 240, 241, 3, 10, 5, 0, 241, 243, 1, 0, 0, 0, 242, 237, 1, 0, 0, 0, 242, 238, 1, 0, 0, 0, 243, 25, 1, 0, 0, 0, 244, 245, 5, 6, 0, 0, 245, 250, 3, 38, 19, 0, 246, 247, 5, 34, 0, 0, 247, 249, 3, 38, 19, 0, 248, 246, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 254, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 255, 3, 28, 14, 0, 254, 253, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 27, 1, 0, 0, 0, 256, 257, 5, 64, 0, 0, 257, 258, 5, 72, 0, 0, 258, 263, 3, 38, 19, 0, 259, 260, 5, 34, 0, 0, 260, 262, 3, 38, 19, 0, 261, 259, 1, 0, 0, 0, 262, 265, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264, 266, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 266, 267, 5, 65, 0, 0, 267, 29, 1, 0, 0, 0, 268, 269, 5, 4, 0, 0, 269, 270, 3, 22, 11, 0, 270, 31, 1, 0, 0, 0, 271, 273, 5, 17, 0, 0, 272, 274, 3, 22, 11, 0, 273, 272, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 277, 1, 0, 0, 0, 275, 276, 5, 30, 0, 0, 276, 278, 3, 36, 18, 0, 277, 275, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 33, 1, 0, 0, 0, 279, 280, 5, 8, 0, 0, 280, 283, 3, 22, 11, 0, 281, 282, 5, 30, 0, 0, 282, 284, 3, 36, 18, 0, 283, 281, 1, 0, 0, 0, 283, 284, 1, 0, 0, 0, 284, 35, 1, 0, 0, 0, 285, 290, 3, 40, 20, 0, 286, 287, 5, 34, 0, 0, 287, 289, 3, 40, 20, 0, 288, 286, 1, 0, 0, 0, 289, 292, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 290, 291, 1, 0, 0, 0, 291, 37, 1, 0, 0, 0, 292, 290, 1, 0, 0, 0, 293, 294, 7, 2, 0, 0, 294, 39, 1, 0, 0, 0, 295, 300, 3, 42, 21, 0, 296, 297, 5, 36, 0, 0, 297, 299, 3, 42, 21, 0, 298, 296, 1, 0, 0, 0, 299, 302, 1, 0, 0, 0, 300, 298, 1, 0, 0, 0, 300, 301, 1, 0, 0, 0, 301, 41, 1, 0, 0, 0, 302, 300, 1, 0, 0, 0, 303, 304, 7, 3, 0, 0, 304, 43, 1, 0, 0, 0, 305, 348, 5, 44, 0, 0, 306, 307, 3, 76, 38, 0, 307, 308, 5, 66, 0, 0, 308, 348, 1, 0, 0, 0, 309, 348, 3, 74, 37, 0, 310, 348, 3, 76, 38, 0, 311, 348, 3, 70, 35, 0, 312, 348, 5, 47, 0, 0, 313, 348, 3, 78, 39, 0, 314, 315, 5, 64, 0, 0, 315, 320, 3, 72, 36, 0, 316, 317, 5, 34, 0, 0, 317, 319, 3, 72, 36, 0, 318, 316, 1, 0, 0, 0, 319, 322, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 323, 1, 0, 0, 0, 322, 320, 1, 0, 0, 0, 323, 324, 5, 65, 0, 0, 324, 348, 1, 0, 0, 0, 325, 326, 5, 64, 0, 0, 326, 331, 3, 70, 35, 0, 327, 328, 5, 34, 0, 0, 328, 330, 3, 70, 35, 0, 329, 327, 1, 0, 0, 0, 330, 333, 1, 0, 0, 0, 331, 329, 1, 0, 0, 0, 331, 332, 1, 0, 0, 0, 332, 334, 1, 0, 0, 0, 333, 331, 1, 0, 0, 0, 334, 335, 5, 65, 0, 0, 335, 348, 1, 0, 0, 0, 336, 337, 5, 64, 0, 0, 337, 342, 3, 78, 39, 0, 338, 339, 5, 34, 0, 0, 339, 341, 3, 78, 39, 0, 340, 338, 1, 0, 0, 0, 341, 344, 1, 0, 0, 0, 342, 340, 1, 0, 0, 0, 342, 343, 1, 0, 0, 0, 343, 345, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 345, 346, 5, 65, 0, 0, 346, 348, 1, 0, 0, 0, 347, 305, 1, 0, 0, 0, 347, 306, 1, 0, 0, 0, 347, 309, 1, 0, 0, 0, 347, 310, 1, 0, 0, 0, 347, 311, 1, 0, 0, 0, 347, 312, 1, 0, 0, 0, 347, 313, 1, 0, 0, 0, 347, 314, 1, 0, 0, 0, 347, 325, 1, 0, 0, 0, 347, 336, 1, 0, 0, 0, 348, 45, 1, 0, 0, 0, 349, 350, 5, 10, 0, 0, 350, 351, 5, 28, 0, 0, 351, 47, 1, 0, 0, 0, 352, 353, 5, 16, 0, 0, 353, 358, 3, 50, 25, 0, 354, 355, 5, 34, 0, 0, 355, 357, 3, 50, 25, 0, 356, 354, 1, 0, 0, 0, 357, 360, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 49, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 361, 363, 3, 10, 5, 0, 362, 364, 7, 4, 0, 0, 363, 362, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 367, 1, 0, 0, 0, 365, 366, 5, 45, 0, 0, 366, 368, 7, 5, 0, 0, 367, 365, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 51, 1, 0, 0, 0, 369, 370, 5, 9, 0, 0, 370, 375, 3, 38, 19, 0, 371, 372, 5, 34, 0, 0, 372, 374, 3, 38, 19, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 388, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 379, 5, 12, 0, 0, 379, 384, 3, 38, 19, 0, 380, 381, 5, 34, 0, 0, 381, 383, 3, 38, 19, 0, 382, 380, 1, 0, 0, 0, 383, 386, 1, 0, 0, 0, 384, 382, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 388, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0, 387, 369, 1, 0, 0, 0, 387, 378, 1, 0, 0, 0, 388, 53, 1, 0, 0, 0, 389, 390, 5, 2, 0, 0, 390, 395, 3, 38, 19, 0, 391, 392, 5, 34, 0, 0, 392, 394, 3, 38, 19, 0, 393, 391, 1, 0, 0, 0, 394, 397, 1, 0, 0, 0, 395, 393, 1, 0, 0, 0, 395, 396, 1, 0, 0, 0, 396, 55, 1, 0, 0, 0, 397, 395, 1, 0, 0, 0, 398, 399, 5, 13, 0, 0, 399, 404, 3, 58, 29, 0, 400, 401, 5, 34, 0, 0, 401, 403, 3, 58, 29, 0, 402, 400, 1, 0, 0, 0, 403, 406, 1, 0, 0, 0, 404, 402, 1, 0, 0, 0, 404, 405, 1, 0, 0, 0, 405, 57, 1, 0, 0, 0, 406, 404, 1, 0, 0, 0, 407, 408, 3, 38, 19, 0, 408, 409, 5, 71, 0, 0, 409, 410, 3, 38, 19, 0, 410, 59, 1, 0, 0, 0, 411, 412, 5, 1, 0, 0, 412, 413, 3, 18, 9, 0, 413, 415, 3, 78, 39, 0, 414, 416, 3, 66, 33, 0, 415, 414, 1, 0, 0, 0, 415, 416, 1, 0, 0, 0, 416, 61, 1, 0, 0, 0, 417, 418, 5, 7, 0, 0, 418, 419, 3, 18, 9, 0, 419, 420, 3, 78, 39, 0, 420, 63, 1, 0, 0, 0, 421, 422, 5, 11, 0, 0, 422, 423, 3, 38, 19, 0, 423, 65, 1, 0, 0, 0, 424, 429, 3, 68, 34, 0, 425, 426, 5, 34, 0, 0, 426, 428, 3, 68, 34, 0, 427, 425, 1, 0, 0, 0, 428, 431, 1, 0, 0, 0, 429, 427, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 67, 1, 0, 0, 0, 431, 429, 1, 0, 0, 0, 432, 433, 3, 42, 21, 0, 433, 434, 5, 33, 0, 0, 434, 435, 3, 44, 22, 0, 435, 69, 1, 0, 0, 0, 436, 437, 7, 6, 0, 0, 437, 71, 1, 0, 0, 0, 438, 441, 3, 74, 37, 0, 439, 441, 3, 76, 38, 0, 440, 438, 1, 0, 0, 0, 440, 439, 1, 0, 0, 0, 441, 73, 1, 0, 0, 0, 442, 444, 7, 0, 0, 0, 443, 442, 1, 0, 0, 0, 443, 444, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 446, 5, 29, 0, 0, 446, 75, 1, 0, 0, 0, 447, 449, 7, 0, 0, 0, 448, 447, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, 449, 450, 1, 0, 0, 0, 450, 451, 5, 28, 0, 0, 451, 77, 1, 0, 0, 0, 452, 453, 5, 27, 0, 0, 453, 79, 1, 0, 0, 0, 454, 455, 7, 7, 0, 0, 455, 81, 1, 0, 0, 0, 456, 457, 5, 5, 0, 0, 457, 458, 3, 84, 42, 0, 458, 83, 1, 0, 0, 0, 459, 460, 5, 64, 0, 0, 460, 461, 3, 2, 1, 0, 461, 462, 5, 65, 0, 0, 462, 85, 1, 0, 0, 0, 463, 464, 5, 15, 0, 0, 464, 468, 5, 51, 0, 0, 465, 466, 5, 15, 0, 0, 466, 468, 5, 52, 0, 0, 467, 463, 1, 0, 0, 0, 467, 465, 1, 0, 0, 0, 468, 87, 1, 0, 0, 0, 469, 470, 5, 3, 0, 0, 470, 473, 3, 38, 19, 0, 471, 472, 5, 73, 0, 0, 472, 474, 3, 38, 19, 0, 473, 471, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 484, 1, 0, 0, 0, 475, 476, 5, 74, 0, 0, 476, 481, 3, 90, 45, 0, 477, 478, 5, 34, 0, 0, 478, 480, 3, 90, 45, 0, 479, 477, 1, 0, 0, 0, 480, 483, 1, 0, 0, 0, 481, 479, 1, 0, 0, 0, 481, 482, 1, 0, 0, 0, 482, 485, 1, 0, 0, 0, 483, 481, 1, 0, 0, 0, 484, 475, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 89, 1, 0, 0, 0, 486, 487, 3, 38, 19, 0, 487, 488, 5, 33, 0, 0, 488, 490, 1, 0, 0, 0, 489, 486, 1, 0, 0, 0, 489, 490, 1, 0, 0, 0, 490, 491, 1, 0, 0, 0, 491, 492, 3, 38, 19, 0, 492, 91, 1, 0, 0, 0, 50, 103, 110, 125, 137, 146, 151, 159, 161, 166, 173, 178, 185, 191, 199, 201, 217, 220, 224, 234, 242, 250, 254, 263, 273, 277, 283, 290, 300, 320, 331, 342, 347, 358, 363, 367, 375, 384, 387, 395, 404, 415, 429, 440, 443, 448, 467, 473, 481, 484, 489] \ No newline at end of file +[4, 1, 81, 501, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 102, 8, 1, 10, 1, 12, 1, 105, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 111, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 126, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 138, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 145, 8, 5, 10, 5, 12, 5, 148, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 155, 8, 5, 1, 5, 1, 5, 3, 5, 159, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 167, 8, 5, 10, 5, 12, 5, 170, 9, 5, 1, 6, 1, 6, 3, 6, 174, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 181, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 186, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 193, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 199, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 207, 8, 8, 10, 8, 12, 8, 210, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 223, 8, 9, 10, 9, 12, 9, 226, 9, 9, 3, 9, 228, 8, 9, 1, 9, 1, 9, 3, 9, 232, 8, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 5, 11, 240, 8, 11, 10, 11, 12, 11, 243, 9, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 250, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 256, 8, 13, 10, 13, 12, 13, 259, 9, 13, 1, 13, 3, 13, 262, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 5, 14, 269, 8, 14, 10, 14, 12, 14, 272, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 281, 8, 16, 1, 16, 1, 16, 3, 16, 285, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 291, 8, 17, 1, 18, 1, 18, 1, 18, 5, 18, 296, 8, 18, 10, 18, 12, 18, 299, 9, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 5, 20, 306, 8, 20, 10, 20, 12, 20, 309, 9, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 326, 8, 22, 10, 22, 12, 22, 329, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 337, 8, 22, 10, 22, 12, 22, 340, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 348, 8, 22, 10, 22, 12, 22, 351, 9, 22, 1, 22, 1, 22, 3, 22, 355, 8, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 5, 24, 364, 8, 24, 10, 24, 12, 24, 367, 9, 24, 1, 25, 1, 25, 3, 25, 371, 8, 25, 1, 25, 1, 25, 3, 25, 375, 8, 25, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 381, 8, 26, 10, 26, 12, 26, 384, 9, 26, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 390, 8, 26, 10, 26, 12, 26, 393, 9, 26, 3, 26, 395, 8, 26, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27, 401, 8, 27, 10, 27, 12, 27, 404, 9, 27, 1, 28, 1, 28, 1, 28, 1, 28, 5, 28, 410, 8, 28, 10, 28, 12, 28, 413, 9, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 423, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 5, 33, 435, 8, 33, 10, 33, 12, 33, 438, 9, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 448, 8, 36, 1, 37, 3, 37, 451, 8, 37, 1, 37, 1, 37, 1, 38, 3, 38, 456, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 475, 8, 43, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 481, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 487, 8, 44, 10, 44, 12, 44, 490, 9, 44, 3, 44, 492, 8, 44, 1, 45, 1, 45, 1, 45, 3, 45, 497, 8, 45, 1, 45, 1, 45, 1, 45, 0, 3, 2, 10, 16, 46, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 0, 8, 1, 0, 60, 61, 1, 0, 62, 64, 1, 0, 76, 77, 1, 0, 67, 68, 2, 0, 32, 32, 35, 35, 1, 0, 38, 39, 2, 0, 37, 37, 51, 51, 1, 0, 54, 59, 531, 0, 92, 1, 0, 0, 0, 2, 95, 1, 0, 0, 0, 4, 110, 1, 0, 0, 0, 6, 125, 1, 0, 0, 0, 8, 127, 1, 0, 0, 0, 10, 158, 1, 0, 0, 0, 12, 185, 1, 0, 0, 0, 14, 192, 1, 0, 0, 0, 16, 198, 1, 0, 0, 0, 18, 231, 1, 0, 0, 0, 20, 233, 1, 0, 0, 0, 22, 236, 1, 0, 0, 0, 24, 249, 1, 0, 0, 0, 26, 251, 1, 0, 0, 0, 28, 263, 1, 0, 0, 0, 30, 275, 1, 0, 0, 0, 32, 278, 1, 0, 0, 0, 34, 286, 1, 0, 0, 0, 36, 292, 1, 0, 0, 0, 38, 300, 1, 0, 0, 0, 40, 302, 1, 0, 0, 0, 42, 310, 1, 0, 0, 0, 44, 354, 1, 0, 0, 0, 46, 356, 1, 0, 0, 0, 48, 359, 1, 0, 0, 0, 50, 368, 1, 0, 0, 0, 52, 394, 1, 0, 0, 0, 54, 396, 1, 0, 0, 0, 56, 405, 1, 0, 0, 0, 58, 414, 1, 0, 0, 0, 60, 418, 1, 0, 0, 0, 62, 424, 1, 0, 0, 0, 64, 428, 1, 0, 0, 0, 66, 431, 1, 0, 0, 0, 68, 439, 1, 0, 0, 0, 70, 443, 1, 0, 0, 0, 72, 447, 1, 0, 0, 0, 74, 450, 1, 0, 0, 0, 76, 455, 1, 0, 0, 0, 78, 459, 1, 0, 0, 0, 80, 461, 1, 0, 0, 0, 82, 463, 1, 0, 0, 0, 84, 466, 1, 0, 0, 0, 86, 474, 1, 0, 0, 0, 88, 476, 1, 0, 0, 0, 90, 496, 1, 0, 0, 0, 92, 93, 3, 2, 1, 0, 93, 94, 5, 0, 0, 1, 94, 1, 1, 0, 0, 0, 95, 96, 6, 1, -1, 0, 96, 97, 3, 4, 2, 0, 97, 103, 1, 0, 0, 0, 98, 99, 10, 1, 0, 0, 99, 100, 5, 26, 0, 0, 100, 102, 3, 6, 3, 0, 101, 98, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 3, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 111, 3, 82, 41, 0, 107, 111, 3, 26, 13, 0, 108, 111, 3, 20, 10, 0, 109, 111, 3, 86, 43, 0, 110, 106, 1, 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 109, 1, 0, 0, 0, 111, 5, 1, 0, 0, 0, 112, 126, 3, 30, 15, 0, 113, 126, 3, 34, 17, 0, 114, 126, 3, 46, 23, 0, 115, 126, 3, 52, 26, 0, 116, 126, 3, 48, 24, 0, 117, 126, 3, 32, 16, 0, 118, 126, 3, 8, 4, 0, 119, 126, 3, 54, 27, 0, 120, 126, 3, 56, 28, 0, 121, 126, 3, 60, 30, 0, 122, 126, 3, 62, 31, 0, 123, 126, 3, 88, 44, 0, 124, 126, 3, 64, 32, 0, 125, 112, 1, 0, 0, 0, 125, 113, 1, 0, 0, 0, 125, 114, 1, 0, 0, 0, 125, 115, 1, 0, 0, 0, 125, 116, 1, 0, 0, 0, 125, 117, 1, 0, 0, 0, 125, 118, 1, 0, 0, 0, 125, 119, 1, 0, 0, 0, 125, 120, 1, 0, 0, 0, 125, 121, 1, 0, 0, 0, 125, 122, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 125, 124, 1, 0, 0, 0, 126, 7, 1, 0, 0, 0, 127, 128, 5, 18, 0, 0, 128, 129, 3, 10, 5, 0, 129, 9, 1, 0, 0, 0, 130, 131, 6, 5, -1, 0, 131, 132, 5, 44, 0, 0, 132, 159, 3, 10, 5, 7, 133, 159, 3, 14, 7, 0, 134, 159, 3, 12, 6, 0, 135, 137, 3, 14, 7, 0, 136, 138, 5, 44, 0, 0, 137, 136, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 140, 5, 41, 0, 0, 140, 141, 5, 40, 0, 0, 141, 146, 3, 14, 7, 0, 142, 143, 5, 34, 0, 0, 143, 145, 3, 14, 7, 0, 144, 142, 1, 0, 0, 0, 145, 148, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 149, 150, 5, 50, 0, 0, 150, 159, 1, 0, 0, 0, 151, 152, 3, 14, 7, 0, 152, 154, 5, 42, 0, 0, 153, 155, 5, 44, 0, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 156, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 159, 1, 0, 0, 0, 158, 130, 1, 0, 0, 0, 158, 133, 1, 0, 0, 0, 158, 134, 1, 0, 0, 0, 158, 135, 1, 0, 0, 0, 158, 151, 1, 0, 0, 0, 159, 168, 1, 0, 0, 0, 160, 161, 10, 4, 0, 0, 161, 162, 5, 31, 0, 0, 162, 167, 3, 10, 5, 5, 163, 164, 10, 3, 0, 0, 164, 165, 5, 47, 0, 0, 165, 167, 3, 10, 5, 4, 166, 160, 1, 0, 0, 0, 166, 163, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 11, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 3, 14, 7, 0, 172, 174, 5, 44, 0, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 176, 5, 43, 0, 0, 176, 177, 3, 78, 39, 0, 177, 186, 1, 0, 0, 0, 178, 180, 3, 14, 7, 0, 179, 181, 5, 44, 0, 0, 180, 179, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 183, 5, 49, 0, 0, 183, 184, 3, 78, 39, 0, 184, 186, 1, 0, 0, 0, 185, 171, 1, 0, 0, 0, 185, 178, 1, 0, 0, 0, 186, 13, 1, 0, 0, 0, 187, 193, 3, 16, 8, 0, 188, 189, 3, 16, 8, 0, 189, 190, 3, 80, 40, 0, 190, 191, 3, 16, 8, 0, 191, 193, 1, 0, 0, 0, 192, 187, 1, 0, 0, 0, 192, 188, 1, 0, 0, 0, 193, 15, 1, 0, 0, 0, 194, 195, 6, 8, -1, 0, 195, 199, 3, 18, 9, 0, 196, 197, 7, 0, 0, 0, 197, 199, 3, 16, 8, 3, 198, 194, 1, 0, 0, 0, 198, 196, 1, 0, 0, 0, 199, 208, 1, 0, 0, 0, 200, 201, 10, 2, 0, 0, 201, 202, 7, 1, 0, 0, 202, 207, 3, 16, 8, 3, 203, 204, 10, 1, 0, 0, 204, 205, 7, 0, 0, 0, 205, 207, 3, 16, 8, 2, 206, 200, 1, 0, 0, 0, 206, 203, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 17, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 211, 232, 3, 44, 22, 0, 212, 232, 3, 40, 20, 0, 213, 214, 5, 40, 0, 0, 214, 215, 3, 10, 5, 0, 215, 216, 5, 50, 0, 0, 216, 232, 1, 0, 0, 0, 217, 218, 3, 42, 21, 0, 218, 227, 5, 40, 0, 0, 219, 224, 3, 10, 5, 0, 220, 221, 5, 34, 0, 0, 221, 223, 3, 10, 5, 0, 222, 220, 1, 0, 0, 0, 223, 226, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 224, 225, 1, 0, 0, 0, 225, 228, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 227, 219, 1, 0, 0, 0, 227, 228, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 230, 5, 50, 0, 0, 230, 232, 1, 0, 0, 0, 231, 211, 1, 0, 0, 0, 231, 212, 1, 0, 0, 0, 231, 213, 1, 0, 0, 0, 231, 217, 1, 0, 0, 0, 232, 19, 1, 0, 0, 0, 233, 234, 5, 14, 0, 0, 234, 235, 3, 22, 11, 0, 235, 21, 1, 0, 0, 0, 236, 241, 3, 24, 12, 0, 237, 238, 5, 34, 0, 0, 238, 240, 3, 24, 12, 0, 239, 237, 1, 0, 0, 0, 240, 243, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 23, 1, 0, 0, 0, 243, 241, 1, 0, 0, 0, 244, 250, 3, 10, 5, 0, 245, 246, 3, 40, 20, 0, 246, 247, 5, 33, 0, 0, 247, 248, 3, 10, 5, 0, 248, 250, 1, 0, 0, 0, 249, 244, 1, 0, 0, 0, 249, 245, 1, 0, 0, 0, 250, 25, 1, 0, 0, 0, 251, 252, 5, 6, 0, 0, 252, 257, 3, 38, 19, 0, 253, 254, 5, 34, 0, 0, 254, 256, 3, 38, 19, 0, 255, 253, 1, 0, 0, 0, 256, 259, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 261, 1, 0, 0, 0, 259, 257, 1, 0, 0, 0, 260, 262, 3, 28, 14, 0, 261, 260, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 27, 1, 0, 0, 0, 263, 264, 5, 65, 0, 0, 264, 265, 5, 73, 0, 0, 265, 270, 3, 38, 19, 0, 266, 267, 5, 34, 0, 0, 267, 269, 3, 38, 19, 0, 268, 266, 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 270, 271, 1, 0, 0, 0, 271, 273, 1, 0, 0, 0, 272, 270, 1, 0, 0, 0, 273, 274, 5, 66, 0, 0, 274, 29, 1, 0, 0, 0, 275, 276, 5, 4, 0, 0, 276, 277, 3, 22, 11, 0, 277, 31, 1, 0, 0, 0, 278, 280, 5, 17, 0, 0, 279, 281, 3, 22, 11, 0, 280, 279, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 284, 1, 0, 0, 0, 282, 283, 5, 30, 0, 0, 283, 285, 3, 36, 18, 0, 284, 282, 1, 0, 0, 0, 284, 285, 1, 0, 0, 0, 285, 33, 1, 0, 0, 0, 286, 287, 5, 8, 0, 0, 287, 290, 3, 22, 11, 0, 288, 289, 5, 30, 0, 0, 289, 291, 3, 36, 18, 0, 290, 288, 1, 0, 0, 0, 290, 291, 1, 0, 0, 0, 291, 35, 1, 0, 0, 0, 292, 297, 3, 40, 20, 0, 293, 294, 5, 34, 0, 0, 294, 296, 3, 40, 20, 0, 295, 293, 1, 0, 0, 0, 296, 299, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 37, 1, 0, 0, 0, 299, 297, 1, 0, 0, 0, 300, 301, 7, 2, 0, 0, 301, 39, 1, 0, 0, 0, 302, 307, 3, 42, 21, 0, 303, 304, 5, 36, 0, 0, 304, 306, 3, 42, 21, 0, 305, 303, 1, 0, 0, 0, 306, 309, 1, 0, 0, 0, 307, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 41, 1, 0, 0, 0, 309, 307, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, 311, 43, 1, 0, 0, 0, 312, 355, 5, 45, 0, 0, 313, 314, 3, 76, 38, 0, 314, 315, 5, 67, 0, 0, 315, 355, 1, 0, 0, 0, 316, 355, 3, 74, 37, 0, 317, 355, 3, 76, 38, 0, 318, 355, 3, 70, 35, 0, 319, 355, 5, 48, 0, 0, 320, 355, 3, 78, 39, 0, 321, 322, 5, 65, 0, 0, 322, 327, 3, 72, 36, 0, 323, 324, 5, 34, 0, 0, 324, 326, 3, 72, 36, 0, 325, 323, 1, 0, 0, 0, 326, 329, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 330, 1, 0, 0, 0, 329, 327, 1, 0, 0, 0, 330, 331, 5, 66, 0, 0, 331, 355, 1, 0, 0, 0, 332, 333, 5, 65, 0, 0, 333, 338, 3, 70, 35, 0, 334, 335, 5, 34, 0, 0, 335, 337, 3, 70, 35, 0, 336, 334, 1, 0, 0, 0, 337, 340, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 341, 1, 0, 0, 0, 340, 338, 1, 0, 0, 0, 341, 342, 5, 66, 0, 0, 342, 355, 1, 0, 0, 0, 343, 344, 5, 65, 0, 0, 344, 349, 3, 78, 39, 0, 345, 346, 5, 34, 0, 0, 346, 348, 3, 78, 39, 0, 347, 345, 1, 0, 0, 0, 348, 351, 1, 0, 0, 0, 349, 347, 1, 0, 0, 0, 349, 350, 1, 0, 0, 0, 350, 352, 1, 0, 0, 0, 351, 349, 1, 0, 0, 0, 352, 353, 5, 66, 0, 0, 353, 355, 1, 0, 0, 0, 354, 312, 1, 0, 0, 0, 354, 313, 1, 0, 0, 0, 354, 316, 1, 0, 0, 0, 354, 317, 1, 0, 0, 0, 354, 318, 1, 0, 0, 0, 354, 319, 1, 0, 0, 0, 354, 320, 1, 0, 0, 0, 354, 321, 1, 0, 0, 0, 354, 332, 1, 0, 0, 0, 354, 343, 1, 0, 0, 0, 355, 45, 1, 0, 0, 0, 356, 357, 5, 10, 0, 0, 357, 358, 5, 28, 0, 0, 358, 47, 1, 0, 0, 0, 359, 360, 5, 16, 0, 0, 360, 365, 3, 50, 25, 0, 361, 362, 5, 34, 0, 0, 362, 364, 3, 50, 25, 0, 363, 361, 1, 0, 0, 0, 364, 367, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, 1, 0, 0, 0, 366, 49, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 368, 370, 3, 10, 5, 0, 369, 371, 7, 4, 0, 0, 370, 369, 1, 0, 0, 0, 370, 371, 1, 0, 0, 0, 371, 374, 1, 0, 0, 0, 372, 373, 5, 46, 0, 0, 373, 375, 7, 5, 0, 0, 374, 372, 1, 0, 0, 0, 374, 375, 1, 0, 0, 0, 375, 51, 1, 0, 0, 0, 376, 377, 5, 9, 0, 0, 377, 382, 3, 38, 19, 0, 378, 379, 5, 34, 0, 0, 379, 381, 3, 38, 19, 0, 380, 378, 1, 0, 0, 0, 381, 384, 1, 0, 0, 0, 382, 380, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 395, 1, 0, 0, 0, 384, 382, 1, 0, 0, 0, 385, 386, 5, 12, 0, 0, 386, 391, 3, 38, 19, 0, 387, 388, 5, 34, 0, 0, 388, 390, 3, 38, 19, 0, 389, 387, 1, 0, 0, 0, 390, 393, 1, 0, 0, 0, 391, 389, 1, 0, 0, 0, 391, 392, 1, 0, 0, 0, 392, 395, 1, 0, 0, 0, 393, 391, 1, 0, 0, 0, 394, 376, 1, 0, 0, 0, 394, 385, 1, 0, 0, 0, 395, 53, 1, 0, 0, 0, 396, 397, 5, 2, 0, 0, 397, 402, 3, 38, 19, 0, 398, 399, 5, 34, 0, 0, 399, 401, 3, 38, 19, 0, 400, 398, 1, 0, 0, 0, 401, 404, 1, 0, 0, 0, 402, 400, 1, 0, 0, 0, 402, 403, 1, 0, 0, 0, 403, 55, 1, 0, 0, 0, 404, 402, 1, 0, 0, 0, 405, 406, 5, 13, 0, 0, 406, 411, 3, 58, 29, 0, 407, 408, 5, 34, 0, 0, 408, 410, 3, 58, 29, 0, 409, 407, 1, 0, 0, 0, 410, 413, 1, 0, 0, 0, 411, 409, 1, 0, 0, 0, 411, 412, 1, 0, 0, 0, 412, 57, 1, 0, 0, 0, 413, 411, 1, 0, 0, 0, 414, 415, 3, 38, 19, 0, 415, 416, 5, 72, 0, 0, 416, 417, 3, 38, 19, 0, 417, 59, 1, 0, 0, 0, 418, 419, 5, 1, 0, 0, 419, 420, 3, 18, 9, 0, 420, 422, 3, 78, 39, 0, 421, 423, 3, 66, 33, 0, 422, 421, 1, 0, 0, 0, 422, 423, 1, 0, 0, 0, 423, 61, 1, 0, 0, 0, 424, 425, 5, 7, 0, 0, 425, 426, 3, 18, 9, 0, 426, 427, 3, 78, 39, 0, 427, 63, 1, 0, 0, 0, 428, 429, 5, 11, 0, 0, 429, 430, 3, 38, 19, 0, 430, 65, 1, 0, 0, 0, 431, 436, 3, 68, 34, 0, 432, 433, 5, 34, 0, 0, 433, 435, 3, 68, 34, 0, 434, 432, 1, 0, 0, 0, 435, 438, 1, 0, 0, 0, 436, 434, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 67, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 439, 440, 3, 42, 21, 0, 440, 441, 5, 33, 0, 0, 441, 442, 3, 44, 22, 0, 442, 69, 1, 0, 0, 0, 443, 444, 7, 6, 0, 0, 444, 71, 1, 0, 0, 0, 445, 448, 3, 74, 37, 0, 446, 448, 3, 76, 38, 0, 447, 445, 1, 0, 0, 0, 447, 446, 1, 0, 0, 0, 448, 73, 1, 0, 0, 0, 449, 451, 7, 0, 0, 0, 450, 449, 1, 0, 0, 0, 450, 451, 1, 0, 0, 0, 451, 452, 1, 0, 0, 0, 452, 453, 5, 29, 0, 0, 453, 75, 1, 0, 0, 0, 454, 456, 7, 0, 0, 0, 455, 454, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 458, 5, 28, 0, 0, 458, 77, 1, 0, 0, 0, 459, 460, 5, 27, 0, 0, 460, 79, 1, 0, 0, 0, 461, 462, 7, 7, 0, 0, 462, 81, 1, 0, 0, 0, 463, 464, 5, 5, 0, 0, 464, 465, 3, 84, 42, 0, 465, 83, 1, 0, 0, 0, 466, 467, 5, 65, 0, 0, 467, 468, 3, 2, 1, 0, 468, 469, 5, 66, 0, 0, 469, 85, 1, 0, 0, 0, 470, 471, 5, 15, 0, 0, 471, 475, 5, 52, 0, 0, 472, 473, 5, 15, 0, 0, 473, 475, 5, 53, 0, 0, 474, 470, 1, 0, 0, 0, 474, 472, 1, 0, 0, 0, 475, 87, 1, 0, 0, 0, 476, 477, 5, 3, 0, 0, 477, 480, 3, 38, 19, 0, 478, 479, 5, 74, 0, 0, 479, 481, 3, 38, 19, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 491, 1, 0, 0, 0, 482, 483, 5, 75, 0, 0, 483, 488, 3, 90, 45, 0, 484, 485, 5, 34, 0, 0, 485, 487, 3, 90, 45, 0, 486, 484, 1, 0, 0, 0, 487, 490, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 492, 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 491, 482, 1, 0, 0, 0, 491, 492, 1, 0, 0, 0, 492, 89, 1, 0, 0, 0, 493, 494, 3, 38, 19, 0, 494, 495, 5, 33, 0, 0, 495, 497, 1, 0, 0, 0, 496, 493, 1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 3, 38, 19, 0, 499, 91, 1, 0, 0, 0, 51, 103, 110, 125, 137, 146, 154, 158, 166, 168, 173, 180, 185, 192, 198, 206, 208, 224, 227, 231, 241, 249, 257, 261, 270, 280, 284, 290, 297, 307, 327, 338, 349, 354, 365, 370, 374, 382, 391, 394, 402, 411, 422, 436, 447, 450, 455, 474, 480, 488, 491, 496] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java index fffa822231681..b5eac5f58f9f6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java @@ -23,13 +23,13 @@ public class EsqlBaseParser extends Parser { WS=22, EXPLAIN_WS=23, EXPLAIN_LINE_COMMENT=24, EXPLAIN_MULTILINE_COMMENT=25, PIPE=26, STRING=27, INTEGER_LITERAL=28, DECIMAL_LITERAL=29, BY=30, AND=31, ASC=32, ASSIGN=33, COMMA=34, DESC=35, DOT=36, FALSE=37, FIRST=38, LAST=39, - LP=40, IN=41, LIKE=42, NOT=43, NULL=44, NULLS=45, OR=46, PARAM=47, RLIKE=48, - RP=49, TRUE=50, INFO=51, FUNCTIONS=52, EQ=53, NEQ=54, LT=55, LTE=56, GT=57, - GTE=58, PLUS=59, MINUS=60, ASTERISK=61, SLASH=62, PERCENT=63, OPENING_BRACKET=64, - CLOSING_BRACKET=65, UNQUOTED_IDENTIFIER=66, QUOTED_IDENTIFIER=67, EXPR_LINE_COMMENT=68, - EXPR_MULTILINE_COMMENT=69, EXPR_WS=70, AS=71, METADATA=72, ON=73, WITH=74, - SRC_UNQUOTED_IDENTIFIER=75, SRC_QUOTED_IDENTIFIER=76, SRC_LINE_COMMENT=77, - SRC_MULTILINE_COMMENT=78, SRC_WS=79, EXPLAIN_PIPE=80; + LP=40, IN=41, IS=42, LIKE=43, NOT=44, NULL=45, NULLS=46, OR=47, PARAM=48, + RLIKE=49, RP=50, TRUE=51, INFO=52, FUNCTIONS=53, EQ=54, NEQ=55, LT=56, + LTE=57, GT=58, GTE=59, PLUS=60, MINUS=61, ASTERISK=62, SLASH=63, PERCENT=64, + OPENING_BRACKET=65, CLOSING_BRACKET=66, UNQUOTED_IDENTIFIER=67, QUOTED_IDENTIFIER=68, + EXPR_LINE_COMMENT=69, EXPR_MULTILINE_COMMENT=70, EXPR_WS=71, AS=72, METADATA=73, + ON=74, WITH=75, SRC_UNQUOTED_IDENTIFIER=76, SRC_QUOTED_IDENTIFIER=77, + SRC_LINE_COMMENT=78, SRC_MULTILINE_COMMENT=79, SRC_WS=80, EXPLAIN_PIPE=81; public static final int RULE_singleStatement = 0, RULE_query = 1, RULE_sourceCommand = 2, RULE_processingCommand = 3, RULE_whereCommand = 4, RULE_booleanExpression = 5, RULE_regexBooleanExpression = 6, @@ -68,8 +68,8 @@ private static String[] makeLiteralNames() { "'rename'", "'row'", "'show'", "'sort'", "'stats'", "'where'", null, null, null, null, null, null, null, null, null, null, null, "'by'", "'and'", "'asc'", null, null, "'desc'", "'.'", "'false'", "'first'", "'last'", - "'('", "'in'", "'like'", "'not'", "'null'", "'nulls'", "'or'", "'?'", - "'rlike'", "')'", "'true'", "'info'", "'functions'", "'=='", "'!='", + "'('", "'in'", "'is'", "'like'", "'not'", "'null'", "'nulls'", "'or'", + "'?'", "'rlike'", "')'", "'true'", "'info'", "'functions'", "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", null, "']'", null, null, null, null, null, "'as'", "'metadata'", "'on'", "'with'" }; @@ -83,9 +83,9 @@ private static String[] makeSymbolicNames() { "WS", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", - "IN", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", - "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", - "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", + "TRUE", "INFO", "FUNCTIONS", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", @@ -668,6 +668,29 @@ public T accept(ParseTreeVisitor visitor) { } } @SuppressWarnings("CheckReturnValue") + public static class IsNullContext extends BooleanExpressionContext { + public ValueExpressionContext valueExpression() { + return getRuleContext(ValueExpressionContext.class,0); + } + public TerminalNode IS() { return getToken(EsqlBaseParser.IS, 0); } + public TerminalNode NULL() { return getToken(EsqlBaseParser.NULL, 0); } + public TerminalNode NOT() { return getToken(EsqlBaseParser.NOT, 0); } + public IsNullContext(BooleanExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterIsNull(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitIsNull(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor)visitor).visitIsNull(this); + else return visitor.visitChildren(this); + } + } + @SuppressWarnings("CheckReturnValue") public static class RegexExpressionContext extends BooleanExpressionContext { public RegexBooleanExpressionContext regexBooleanExpression() { return getRuleContext(RegexBooleanExpressionContext.class,0); @@ -763,9 +786,9 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(151); + setState(158); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: { _localctx = new LogicalNotContext(_localctx); @@ -775,7 +798,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc setState(131); match(NOT); setState(132); - booleanExpression(6); + booleanExpression(7); } break; case 2: @@ -839,30 +862,53 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc match(RP); } break; + case 5: + { + _localctx = new IsNullContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(151); + valueExpression(); + setState(152); + match(IS); + setState(154); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==NOT) { + { + setState(153); + match(NOT); + } + } + + setState(156); + match(NULL); + } + break; } _ctx.stop = _input.LT(-1); - setState(161); + setState(168); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,7,_ctx); + _alt = getInterpreter().adaptivePredict(_input,8,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(159); + setState(166); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { case 1: { _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(153); - if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(154); + setState(160); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(161); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(155); - ((LogicalBinaryContext)_localctx).right = booleanExpression(4); + setState(162); + ((LogicalBinaryContext)_localctx).right = booleanExpression(5); } break; case 2: @@ -870,20 +916,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(156); - if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(157); + setState(163); + if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(164); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(158); - ((LogicalBinaryContext)_localctx).right = booleanExpression(3); + setState(165); + ((LogicalBinaryContext)_localctx).right = booleanExpression(4); } break; } } } - setState(163); + setState(170); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,7,_ctx); + _alt = getInterpreter().adaptivePredict(_input,8,_ctx); } } } @@ -935,48 +981,48 @@ public final RegexBooleanExpressionContext regexBooleanExpression() throws Recog enterRule(_localctx, 12, RULE_regexBooleanExpression); int _la; try { - setState(178); + setState(185); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(164); + setState(171); valueExpression(); - setState(166); + setState(173); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(165); + setState(172); match(NOT); } } - setState(168); + setState(175); ((RegexBooleanExpressionContext)_localctx).kind = match(LIKE); - setState(169); + setState(176); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(171); + setState(178); valueExpression(); - setState(173); + setState(180); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(172); + setState(179); match(NOT); } } - setState(175); + setState(182); ((RegexBooleanExpressionContext)_localctx).kind = match(RLIKE); - setState(176); + setState(183); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; @@ -1058,14 +1104,14 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, getState()); enterRule(_localctx, 14, RULE_valueExpression); try { - setState(185); + setState(192); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { case 1: _localctx = new ValueExpressionDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(180); + setState(187); operatorExpression(0); } break; @@ -1073,11 +1119,11 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio _localctx = new ComparisonContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(181); + setState(188); ((ComparisonContext)_localctx).left = operatorExpression(0); - setState(182); + setState(189); comparisonOperator(); - setState(183); + setState(190); ((ComparisonContext)_localctx).right = operatorExpression(0); } break; @@ -1197,16 +1243,16 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE int _alt; enterOuterAlt(_localctx, 1); { - setState(191); + setState(198); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: { _localctx = new OperatorExpressionDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(188); + setState(195); primaryExpression(); } break; @@ -1215,7 +1261,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(189); + setState(196); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1226,34 +1272,34 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(190); + setState(197); operatorExpression(3); } break; } _ctx.stop = _input.LT(-1); - setState(201); + setState(208); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,14,_ctx); + _alt = getInterpreter().adaptivePredict(_input,15,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(199); + setState(206); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { case 1: { _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); - setState(193); + setState(200); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(194); + setState(201); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); - if ( !(((_la) & ~0x3f) == 0 && ((1L << _la) & -2305843009213693952L) != 0) ) { + if ( !((((_la - 62)) & ~0x3f) == 0 && ((1L << (_la - 62)) & 7L) != 0) ) { ((ArithmeticBinaryContext)_localctx).operator = (Token)_errHandler.recoverInline(this); } else { @@ -1261,7 +1307,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(195); + setState(202); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3); } break; @@ -1270,9 +1316,9 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); - setState(196); + setState(203); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(197); + setState(204); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1283,16 +1329,16 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(198); + setState(205); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(2); } break; } } } - setState(203); + setState(210); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,14,_ctx); + _alt = getInterpreter().adaptivePredict(_input,15,_ctx); } } } @@ -1419,14 +1465,14 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce enterRule(_localctx, 18, RULE_primaryExpression); int _la; try { - setState(224); + setState(231); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: _localctx = new ConstantDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(204); + setState(211); constant(); } break; @@ -1434,7 +1480,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new DereferenceContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(205); + setState(212); qualifiedName(); } break; @@ -1442,11 +1488,11 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new ParenthesizedExpressionContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(206); + setState(213); match(LP); - setState(207); + setState(214); booleanExpression(0); - setState(208); + setState(215); match(RP); } break; @@ -1454,37 +1500,37 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new FunctionExpressionContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(210); + setState(217); identifier(); - setState(211); + setState(218); match(LP); - setState(220); + setState(227); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la - 27)) & ~0x3f) == 0 && ((1L << (_la - 27)) & 1799600940039L) != 0) { + if ((((_la - 27)) & ~0x3f) == 0 && ((1L << (_la - 27)) & 3599201870855L) != 0) { { - setState(212); + setState(219); booleanExpression(0); - setState(217); + setState(224); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(213); + setState(220); match(COMMA); - setState(214); + setState(221); booleanExpression(0); } } - setState(219); + setState(226); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(222); + setState(229); match(RP); } break; @@ -1532,9 +1578,9 @@ public final RowCommandContext rowCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(226); + setState(233); match(ROW); - setState(227); + setState(234); fields(); } } @@ -1587,25 +1633,25 @@ public final FieldsContext fields() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(229); + setState(236); field(); - setState(234); + setState(241); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,18,_ctx); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(230); + setState(237); match(COMMA); - setState(231); + setState(238); field(); } } } - setState(236); + setState(243); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,18,_ctx); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); } } } @@ -1652,24 +1698,24 @@ public final FieldContext field() throws RecognitionException { FieldContext _localctx = new FieldContext(_ctx, getState()); enterRule(_localctx, 24, RULE_field); try { - setState(242); + setState(249); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(237); + setState(244); booleanExpression(0); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(238); + setState(245); qualifiedName(); - setState(239); + setState(246); match(ASSIGN); - setState(240); + setState(247); booleanExpression(0); } break; @@ -1728,34 +1774,34 @@ public final FromCommandContext fromCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(244); + setState(251); match(FROM); - setState(245); + setState(252); sourceIdentifier(); - setState(250); + setState(257); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,20,_ctx); + _alt = getInterpreter().adaptivePredict(_input,21,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(246); + setState(253); match(COMMA); - setState(247); + setState(254); sourceIdentifier(); } } } - setState(252); + setState(259); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,20,_ctx); + _alt = getInterpreter().adaptivePredict(_input,21,_ctx); } - setState(254); + setState(261); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) { case 1: { - setState(253); + setState(260); metadata(); } break; @@ -1814,29 +1860,29 @@ public final MetadataContext metadata() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(256); + setState(263); match(OPENING_BRACKET); - setState(257); + setState(264); match(METADATA); - setState(258); + setState(265); sourceIdentifier(); - setState(263); + setState(270); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(259); + setState(266); match(COMMA); - setState(260); + setState(267); sourceIdentifier(); } } - setState(265); + setState(272); _errHandler.sync(this); _la = _input.LA(1); } - setState(266); + setState(273); match(CLOSING_BRACKET); } } @@ -1882,9 +1928,9 @@ public final EvalCommandContext evalCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(268); + setState(275); match(EVAL); - setState(269); + setState(276); fields(); } } @@ -1934,26 +1980,26 @@ public final StatsCommandContext statsCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(271); + setState(278); match(STATS); - setState(273); + setState(280); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,24,_ctx) ) { case 1: { - setState(272); + setState(279); fields(); } break; } - setState(277); + setState(284); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,24,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { case 1: { - setState(275); + setState(282); match(BY); - setState(276); + setState(283); grouping(); } break; @@ -2006,18 +2052,18 @@ public final InlinestatsCommandContext inlinestatsCommand() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(279); + setState(286); match(INLINESTATS); - setState(280); + setState(287); fields(); - setState(283); + setState(290); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) { case 1: { - setState(281); + setState(288); match(BY); - setState(282); + setState(289); grouping(); } break; @@ -2073,25 +2119,25 @@ public final GroupingContext grouping() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(285); + setState(292); qualifiedName(); - setState(290); + setState(297); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + _alt = getInterpreter().adaptivePredict(_input,27,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(286); + setState(293); match(COMMA); - setState(287); + setState(294); qualifiedName(); } } } - setState(292); + setState(299); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + _alt = getInterpreter().adaptivePredict(_input,27,_ctx); } } } @@ -2136,7 +2182,7 @@ public final SourceIdentifierContext sourceIdentifier() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(293); + setState(300); _la = _input.LA(1); if ( !(_la==SRC_UNQUOTED_IDENTIFIER || _la==SRC_QUOTED_IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2197,25 +2243,25 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(295); + setState(302); identifier(); - setState(300); + setState(307); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,27,_ctx); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(296); + setState(303); match(DOT); - setState(297); + setState(304); identifier(); } } } - setState(302); + setState(309); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,27,_ctx); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); } } } @@ -2260,7 +2306,7 @@ public final IdentifierContext identifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(303); + setState(310); _la = _input.LA(1); if ( !(_la==UNQUOTED_IDENTIFIER || _la==QUOTED_IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2525,14 +2571,14 @@ public final ConstantContext constant() throws RecognitionException { enterRule(_localctx, 44, RULE_constant); int _la; try { - setState(347); + setState(354); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) { case 1: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(305); + setState(312); match(NULL); } break; @@ -2540,9 +2586,9 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new QualifiedIntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(306); + setState(313); integerValue(); - setState(307); + setState(314); match(UNQUOTED_IDENTIFIER); } break; @@ -2550,7 +2596,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(309); + setState(316); decimalValue(); } break; @@ -2558,7 +2604,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(310); + setState(317); integerValue(); } break; @@ -2566,7 +2612,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(311); + setState(318); booleanValue(); } break; @@ -2574,7 +2620,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new InputParamContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(312); + setState(319); match(PARAM); } break; @@ -2582,7 +2628,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(313); + setState(320); string(); } break; @@ -2590,27 +2636,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(314); + setState(321); match(OPENING_BRACKET); - setState(315); + setState(322); numericValue(); - setState(320); + setState(327); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(316); + setState(323); match(COMMA); - setState(317); + setState(324); numericValue(); } } - setState(322); + setState(329); _errHandler.sync(this); _la = _input.LA(1); } - setState(323); + setState(330); match(CLOSING_BRACKET); } break; @@ -2618,27 +2664,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(325); + setState(332); match(OPENING_BRACKET); - setState(326); + setState(333); booleanValue(); - setState(331); + setState(338); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(327); + setState(334); match(COMMA); - setState(328); + setState(335); booleanValue(); } } - setState(333); + setState(340); _errHandler.sync(this); _la = _input.LA(1); } - setState(334); + setState(341); match(CLOSING_BRACKET); } break; @@ -2646,27 +2692,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(336); + setState(343); match(OPENING_BRACKET); - setState(337); + setState(344); string(); - setState(342); + setState(349); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(338); + setState(345); match(COMMA); - setState(339); + setState(346); string(); } } - setState(344); + setState(351); _errHandler.sync(this); _la = _input.LA(1); } - setState(345); + setState(352); match(CLOSING_BRACKET); } break; @@ -2712,9 +2758,9 @@ public final LimitCommandContext limitCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(349); + setState(356); match(LIMIT); - setState(350); + setState(357); match(INTEGER_LITERAL); } } @@ -2768,27 +2814,27 @@ public final SortCommandContext sortCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(352); + setState(359); match(SORT); - setState(353); + setState(360); orderExpression(); - setState(358); + setState(365); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + _alt = getInterpreter().adaptivePredict(_input,33,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(354); + setState(361); match(COMMA); - setState(355); + setState(362); orderExpression(); } } } - setState(360); + setState(367); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + _alt = getInterpreter().adaptivePredict(_input,33,_ctx); } } } @@ -2841,14 +2887,14 @@ public final OrderExpressionContext orderExpression() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(361); + setState(368); booleanExpression(0); - setState(363); + setState(370); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) { case 1: { - setState(362); + setState(369); ((OrderExpressionContext)_localctx).ordering = _input.LT(1); _la = _input.LA(1); if ( !(_la==ASC || _la==DESC) ) { @@ -2862,14 +2908,14 @@ public final OrderExpressionContext orderExpression() throws RecognitionExceptio } break; } - setState(367); + setState(374); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { case 1: { - setState(365); + setState(372); match(NULLS); - setState(366); + setState(373); ((OrderExpressionContext)_localctx).nullOrdering = _input.LT(1); _la = _input.LA(1); if ( !(_la==FIRST || _la==LAST) ) { @@ -2934,60 +2980,60 @@ public final KeepCommandContext keepCommand() throws RecognitionException { enterRule(_localctx, 52, RULE_keepCommand); try { int _alt; - setState(387); + setState(394); _errHandler.sync(this); switch (_input.LA(1)) { case KEEP: enterOuterAlt(_localctx, 1); { - setState(369); + setState(376); match(KEEP); - setState(370); + setState(377); sourceIdentifier(); - setState(375); + setState(382); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,35,_ctx); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(371); + setState(378); match(COMMA); - setState(372); + setState(379); sourceIdentifier(); } } } - setState(377); + setState(384); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,35,_ctx); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); } } break; case PROJECT: enterOuterAlt(_localctx, 2); { - setState(378); + setState(385); match(PROJECT); - setState(379); + setState(386); sourceIdentifier(); - setState(384); + setState(391); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + _alt = getInterpreter().adaptivePredict(_input,37,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(380); + setState(387); match(COMMA); - setState(381); + setState(388); sourceIdentifier(); } } } - setState(386); + setState(393); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + _alt = getInterpreter().adaptivePredict(_input,37,_ctx); } } break; @@ -3045,27 +3091,27 @@ public final DropCommandContext dropCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(389); + setState(396); match(DROP); - setState(390); + setState(397); sourceIdentifier(); - setState(395); + setState(402); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,38,_ctx); + _alt = getInterpreter().adaptivePredict(_input,39,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(391); + setState(398); match(COMMA); - setState(392); + setState(399); sourceIdentifier(); } } } - setState(397); + setState(404); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,38,_ctx); + _alt = getInterpreter().adaptivePredict(_input,39,_ctx); } } } @@ -3119,27 +3165,27 @@ public final RenameCommandContext renameCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(398); + setState(405); match(RENAME); - setState(399); + setState(406); renameClause(); - setState(404); + setState(411); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,39,_ctx); + _alt = getInterpreter().adaptivePredict(_input,40,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(400); + setState(407); match(COMMA); - setState(401); + setState(408); renameClause(); } } } - setState(406); + setState(413); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,39,_ctx); + _alt = getInterpreter().adaptivePredict(_input,40,_ctx); } } } @@ -3190,11 +3236,11 @@ public final RenameClauseContext renameClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(407); + setState(414); ((RenameClauseContext)_localctx).oldName = sourceIdentifier(); - setState(408); + setState(415); match(AS); - setState(409); + setState(416); ((RenameClauseContext)_localctx).newName = sourceIdentifier(); } } @@ -3246,18 +3292,18 @@ public final DissectCommandContext dissectCommand() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(411); + setState(418); match(DISSECT); - setState(412); + setState(419); primaryExpression(); - setState(413); + setState(420); string(); - setState(415); + setState(422); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,41,_ctx) ) { case 1: { - setState(414); + setState(421); commandOptions(); } break; @@ -3309,11 +3355,11 @@ public final GrokCommandContext grokCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(417); + setState(424); match(GROK); - setState(418); + setState(425); primaryExpression(); - setState(419); + setState(426); string(); } } @@ -3359,9 +3405,9 @@ public final MvExpandCommandContext mvExpandCommand() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(421); + setState(428); match(MV_EXPAND); - setState(422); + setState(429); sourceIdentifier(); } } @@ -3414,25 +3460,25 @@ public final CommandOptionsContext commandOptions() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(424); + setState(431); commandOption(); - setState(429); + setState(436); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,41,_ctx); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(425); + setState(432); match(COMMA); - setState(426); + setState(433); commandOption(); } } } - setState(431); + setState(438); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,41,_ctx); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); } } } @@ -3481,11 +3527,11 @@ public final CommandOptionContext commandOption() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(432); + setState(439); identifier(); - setState(433); + setState(440); match(ASSIGN); - setState(434); + setState(441); constant(); } } @@ -3530,7 +3576,7 @@ public final BooleanValueContext booleanValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(436); + setState(443); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -3584,20 +3630,20 @@ public final NumericValueContext numericValue() throws RecognitionException { NumericValueContext _localctx = new NumericValueContext(_ctx, getState()); enterRule(_localctx, 72, RULE_numericValue); try { - setState(440); + setState(447); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,43,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(438); + setState(445); decimalValue(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(439); + setState(446); integerValue(); } break; @@ -3645,12 +3691,12 @@ public final DecimalValueContext decimalValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(443); + setState(450); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(442); + setState(449); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -3663,7 +3709,7 @@ public final DecimalValueContext decimalValue() throws RecognitionException { } } - setState(445); + setState(452); match(DECIMAL_LITERAL); } } @@ -3709,12 +3755,12 @@ public final IntegerValueContext integerValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(448); + setState(455); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(447); + setState(454); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -3727,7 +3773,7 @@ public final IntegerValueContext integerValue() throws RecognitionException { } } - setState(450); + setState(457); match(INTEGER_LITERAL); } } @@ -3770,7 +3816,7 @@ public final StringContext string() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(452); + setState(459); match(STRING); } } @@ -3819,9 +3865,9 @@ public final ComparisonOperatorContext comparisonOperator() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(454); + setState(461); _la = _input.LA(1); - if ( !(((_la) & ~0x3f) == 0 && ((1L << _la) & 567453553048682496L) != 0) ) { + if ( !(((_la) & ~0x3f) == 0 && ((1L << _la) & 1134907106097364992L) != 0) ) { _errHandler.recoverInline(this); } else { @@ -3873,9 +3919,9 @@ public final ExplainCommandContext explainCommand() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(456); + setState(463); match(EXPLAIN); - setState(457); + setState(464); subqueryExpression(); } } @@ -3922,11 +3968,11 @@ public final SubqueryExpressionContext subqueryExpression() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(459); + setState(466); match(OPENING_BRACKET); - setState(460); + setState(467); query(0); - setState(461); + setState(468); match(CLOSING_BRACKET); } } @@ -3996,16 +4042,16 @@ public final ShowCommandContext showCommand() throws RecognitionException { ShowCommandContext _localctx = new ShowCommandContext(_ctx, getState()); enterRule(_localctx, 86, RULE_showCommand); try { - setState(467); + setState(474); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,45,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,46,_ctx) ) { case 1: _localctx = new ShowInfoContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(463); + setState(470); match(SHOW); - setState(464); + setState(471); match(INFO); } break; @@ -4013,9 +4059,9 @@ public final ShowCommandContext showCommand() throws RecognitionException { _localctx = new ShowFunctionsContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(465); + setState(472); match(SHOW); - setState(466); + setState(473); match(FUNCTIONS); } break; @@ -4081,48 +4127,48 @@ public final EnrichCommandContext enrichCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(469); + setState(476); match(ENRICH); - setState(470); + setState(477); ((EnrichCommandContext)_localctx).policyName = sourceIdentifier(); - setState(473); + setState(480); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,46,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { case 1: { - setState(471); + setState(478); match(ON); - setState(472); + setState(479); ((EnrichCommandContext)_localctx).matchField = sourceIdentifier(); } break; } - setState(484); + setState(491); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,48,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { case 1: { - setState(475); + setState(482); match(WITH); - setState(476); + setState(483); enrichWithClause(); - setState(481); + setState(488); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,47,_ctx); + _alt = getInterpreter().adaptivePredict(_input,48,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(477); + setState(484); match(COMMA); - setState(478); + setState(485); enrichWithClause(); } } } - setState(483); + setState(490); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,47,_ctx); + _alt = getInterpreter().adaptivePredict(_input,48,_ctx); } } break; @@ -4176,19 +4222,19 @@ public final EnrichWithClauseContext enrichWithClause() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(489); + setState(496); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { case 1: { - setState(486); + setState(493); ((EnrichWithClauseContext)_localctx).newName = sourceIdentifier(); - setState(487); + setState(494); match(ASSIGN); } break; } - setState(491); + setState(498); ((EnrichWithClauseContext)_localctx).enrichField = sourceIdentifier(); } } @@ -4224,9 +4270,9 @@ private boolean query_sempred(QueryContext _localctx, int predIndex) { private boolean booleanExpression_sempred(BooleanExpressionContext _localctx, int predIndex) { switch (predIndex) { case 1: - return precpred(_ctx, 3); + return precpred(_ctx, 4); case 2: - return precpred(_ctx, 2); + return precpred(_ctx, 3); } return true; } @@ -4241,7 +4287,7 @@ private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, } public static final String _serializedATN = - "\u0004\u0001P\u01ee\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ + "\u0004\u0001Q\u01f5\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0002"+ @@ -4263,301 +4309,307 @@ private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, "\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ "\u0005\u0001\u0005\u0001\u0005\u0003\u0005\u008a\b\u0005\u0001\u0005\u0001"+ "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0005\u0005\u0091\b\u0005\n"+ - "\u0005\f\u0005\u0094\t\u0005\u0001\u0005\u0001\u0005\u0003\u0005\u0098"+ - "\b\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ - "\u0005\u0005\u0005\u00a0\b\u0005\n\u0005\f\u0005\u00a3\t\u0005\u0001\u0006"+ - "\u0001\u0006\u0003\u0006\u00a7\b\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ + "\u0005\f\u0005\u0094\t\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ + "\u0005\u0001\u0005\u0003\u0005\u009b\b\u0005\u0001\u0005\u0001\u0005\u0003"+ + "\u0005\u009f\b\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ + "\u0005\u0001\u0005\u0005\u0005\u00a7\b\u0005\n\u0005\f\u0005\u00aa\t\u0005"+ "\u0001\u0006\u0001\u0006\u0003\u0006\u00ae\b\u0006\u0001\u0006\u0001\u0006"+ - "\u0001\u0006\u0003\u0006\u00b3\b\u0006\u0001\u0007\u0001\u0007\u0001\u0007"+ - "\u0001\u0007\u0001\u0007\u0003\u0007\u00ba\b\u0007\u0001\b\u0001\b\u0001"+ - "\b\u0001\b\u0003\b\u00c0\b\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ - "\b\u0005\b\u00c8\b\b\n\b\f\b\u00cb\t\b\u0001\t\u0001\t\u0001\t\u0001\t"+ - "\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0005\t\u00d8"+ - "\b\t\n\t\f\t\u00db\t\t\u0003\t\u00dd\b\t\u0001\t\u0001\t\u0003\t\u00e1"+ - "\b\t\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\u000b\u0005"+ - "\u000b\u00e9\b\u000b\n\u000b\f\u000b\u00ec\t\u000b\u0001\f\u0001\f\u0001"+ - "\f\u0001\f\u0001\f\u0003\f\u00f3\b\f\u0001\r\u0001\r\u0001\r\u0001\r\u0005"+ - "\r\u00f9\b\r\n\r\f\r\u00fc\t\r\u0001\r\u0003\r\u00ff\b\r\u0001\u000e\u0001"+ - "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0005\u000e\u0106\b\u000e\n"+ - "\u000e\f\u000e\u0109\t\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001"+ - "\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0003\u0010\u0112\b\u0010\u0001"+ - "\u0010\u0001\u0010\u0003\u0010\u0116\b\u0010\u0001\u0011\u0001\u0011\u0001"+ - "\u0011\u0001\u0011\u0003\u0011\u011c\b\u0011\u0001\u0012\u0001\u0012\u0001"+ - "\u0012\u0005\u0012\u0121\b\u0012\n\u0012\f\u0012\u0124\t\u0012\u0001\u0013"+ - "\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0005\u0014\u012b\b\u0014"+ - "\n\u0014\f\u0014\u012e\t\u0014\u0001\u0015\u0001\u0015\u0001\u0016\u0001"+ - "\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+ + "\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006\u00b5\b\u0006\u0001\u0006"+ + "\u0001\u0006\u0001\u0006\u0003\u0006\u00ba\b\u0006\u0001\u0007\u0001\u0007"+ + "\u0001\u0007\u0001\u0007\u0001\u0007\u0003\u0007\u00c1\b\u0007\u0001\b"+ + "\u0001\b\u0001\b\u0001\b\u0003\b\u00c7\b\b\u0001\b\u0001\b\u0001\b\u0001"+ + "\b\u0001\b\u0001\b\u0005\b\u00cf\b\b\n\b\f\b\u00d2\t\b\u0001\t\u0001\t"+ + "\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ + "\t\u0005\t\u00df\b\t\n\t\f\t\u00e2\t\t\u0003\t\u00e4\b\t\u0001\t\u0001"+ + "\t\u0003\t\u00e8\b\t\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001"+ + "\u000b\u0005\u000b\u00f0\b\u000b\n\u000b\f\u000b\u00f3\t\u000b\u0001\f"+ + "\u0001\f\u0001\f\u0001\f\u0001\f\u0003\f\u00fa\b\f\u0001\r\u0001\r\u0001"+ + "\r\u0001\r\u0005\r\u0100\b\r\n\r\f\r\u0103\t\r\u0001\r\u0003\r\u0106\b"+ + "\r\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0005\u000e"+ + "\u010d\b\u000e\n\u000e\f\u000e\u0110\t\u000e\u0001\u000e\u0001\u000e\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0003\u0010\u0119"+ + "\b\u0010\u0001\u0010\u0001\u0010\u0003\u0010\u011d\b\u0010\u0001\u0011"+ + "\u0001\u0011\u0001\u0011\u0001\u0011\u0003\u0011\u0123\b\u0011\u0001\u0012"+ + "\u0001\u0012\u0001\u0012\u0005\u0012\u0128\b\u0012\n\u0012\f\u0012\u012b"+ + "\t\u0012\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0005"+ + "\u0014\u0132\b\u0014\n\u0014\f\u0014\u0135\t\u0014\u0001\u0015\u0001\u0015"+ + "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+ + "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+ + "\u0001\u0016\u0005\u0016\u0146\b\u0016\n\u0016\f\u0016\u0149\t\u0016\u0001"+ "\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0005"+ - "\u0016\u013f\b\u0016\n\u0016\f\u0016\u0142\t\u0016\u0001\u0016\u0001\u0016"+ - "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0005\u0016\u014a\b\u0016"+ - "\n\u0016\f\u0016\u014d\t\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+ - "\u0016\u0001\u0016\u0001\u0016\u0005\u0016\u0155\b\u0016\n\u0016\f\u0016"+ - "\u0158\t\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u015c\b\u0016\u0001"+ - "\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ - "\u0018\u0005\u0018\u0165\b\u0018\n\u0018\f\u0018\u0168\t\u0018\u0001\u0019"+ - "\u0001\u0019\u0003\u0019\u016c\b\u0019\u0001\u0019\u0001\u0019\u0003\u0019"+ - "\u0170\b\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0005\u001a"+ - "\u0176\b\u001a\n\u001a\f\u001a\u0179\t\u001a\u0001\u001a\u0001\u001a\u0001"+ - "\u001a\u0001\u001a\u0005\u001a\u017f\b\u001a\n\u001a\f\u001a\u0182\t\u001a"+ - "\u0003\u001a\u0184\b\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b"+ - "\u0005\u001b\u018a\b\u001b\n\u001b\f\u001b\u018d\t\u001b\u0001\u001c\u0001"+ - "\u001c\u0001\u001c\u0001\u001c\u0005\u001c\u0193\b\u001c\n\u001c\f\u001c"+ - "\u0196\t\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001e"+ - "\u0001\u001e\u0001\u001e\u0001\u001e\u0003\u001e\u01a0\b\u001e\u0001\u001f"+ - "\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001 \u0001!\u0001"+ - "!\u0001!\u0005!\u01ac\b!\n!\f!\u01af\t!\u0001\"\u0001\"\u0001\"\u0001"+ - "\"\u0001#\u0001#\u0001$\u0001$\u0003$\u01b9\b$\u0001%\u0003%\u01bc\b%"+ - "\u0001%\u0001%\u0001&\u0003&\u01c1\b&\u0001&\u0001&\u0001\'\u0001\'\u0001"+ - "(\u0001(\u0001)\u0001)\u0001)\u0001*\u0001*\u0001*\u0001*\u0001+\u0001"+ - "+\u0001+\u0001+\u0003+\u01d4\b+\u0001,\u0001,\u0001,\u0001,\u0003,\u01da"+ - "\b,\u0001,\u0001,\u0001,\u0001,\u0005,\u01e0\b,\n,\f,\u01e3\t,\u0003,"+ - "\u01e5\b,\u0001-\u0001-\u0001-\u0003-\u01ea\b-\u0001-\u0001-\u0001-\u0000"+ - "\u0003\u0002\n\u0010.\u0000\u0002\u0004\u0006\b\n\f\u000e\u0010\u0012"+ - "\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDFHJLNPRTVXZ\u0000"+ - "\b\u0001\u0000;<\u0001\u0000=?\u0001\u0000KL\u0001\u0000BC\u0002\u0000"+ - " ##\u0001\u0000&\'\u0002\u0000%%22\u0001\u00005:\u020a\u0000\\\u0001"+ - "\u0000\u0000\u0000\u0002_\u0001\u0000\u0000\u0000\u0004n\u0001\u0000\u0000"+ - "\u0000\u0006}\u0001\u0000\u0000\u0000\b\u007f\u0001\u0000\u0000\u0000"+ - "\n\u0097\u0001\u0000\u0000\u0000\f\u00b2\u0001\u0000\u0000\u0000\u000e"+ - "\u00b9\u0001\u0000\u0000\u0000\u0010\u00bf\u0001\u0000\u0000\u0000\u0012"+ - "\u00e0\u0001\u0000\u0000\u0000\u0014\u00e2\u0001\u0000\u0000\u0000\u0016"+ - "\u00e5\u0001\u0000\u0000\u0000\u0018\u00f2\u0001\u0000\u0000\u0000\u001a"+ - "\u00f4\u0001\u0000\u0000\u0000\u001c\u0100\u0001\u0000\u0000\u0000\u001e"+ - "\u010c\u0001\u0000\u0000\u0000 \u010f\u0001\u0000\u0000\u0000\"\u0117"+ - "\u0001\u0000\u0000\u0000$\u011d\u0001\u0000\u0000\u0000&\u0125\u0001\u0000"+ - "\u0000\u0000(\u0127\u0001\u0000\u0000\u0000*\u012f\u0001\u0000\u0000\u0000"+ - ",\u015b\u0001\u0000\u0000\u0000.\u015d\u0001\u0000\u0000\u00000\u0160"+ - "\u0001\u0000\u0000\u00002\u0169\u0001\u0000\u0000\u00004\u0183\u0001\u0000"+ - "\u0000\u00006\u0185\u0001\u0000\u0000\u00008\u018e\u0001\u0000\u0000\u0000"+ - ":\u0197\u0001\u0000\u0000\u0000<\u019b\u0001\u0000\u0000\u0000>\u01a1"+ - "\u0001\u0000\u0000\u0000@\u01a5\u0001\u0000\u0000\u0000B\u01a8\u0001\u0000"+ - "\u0000\u0000D\u01b0\u0001\u0000\u0000\u0000F\u01b4\u0001\u0000\u0000\u0000"+ - "H\u01b8\u0001\u0000\u0000\u0000J\u01bb\u0001\u0000\u0000\u0000L\u01c0"+ - "\u0001\u0000\u0000\u0000N\u01c4\u0001\u0000\u0000\u0000P\u01c6\u0001\u0000"+ - "\u0000\u0000R\u01c8\u0001\u0000\u0000\u0000T\u01cb\u0001\u0000\u0000\u0000"+ - "V\u01d3\u0001\u0000\u0000\u0000X\u01d5\u0001\u0000\u0000\u0000Z\u01e9"+ - "\u0001\u0000\u0000\u0000\\]\u0003\u0002\u0001\u0000]^\u0005\u0000\u0000"+ - "\u0001^\u0001\u0001\u0000\u0000\u0000_`\u0006\u0001\uffff\uffff\u0000"+ - "`a\u0003\u0004\u0002\u0000ag\u0001\u0000\u0000\u0000bc\n\u0001\u0000\u0000"+ - "cd\u0005\u001a\u0000\u0000df\u0003\u0006\u0003\u0000eb\u0001\u0000\u0000"+ - "\u0000fi\u0001\u0000\u0000\u0000ge\u0001\u0000\u0000\u0000gh\u0001\u0000"+ - "\u0000\u0000h\u0003\u0001\u0000\u0000\u0000ig\u0001\u0000\u0000\u0000"+ - "jo\u0003R)\u0000ko\u0003\u001a\r\u0000lo\u0003\u0014\n\u0000mo\u0003V"+ - "+\u0000nj\u0001\u0000\u0000\u0000nk\u0001\u0000\u0000\u0000nl\u0001\u0000"+ - "\u0000\u0000nm\u0001\u0000\u0000\u0000o\u0005\u0001\u0000\u0000\u0000"+ - "p~\u0003\u001e\u000f\u0000q~\u0003\"\u0011\u0000r~\u0003.\u0017\u0000"+ - "s~\u00034\u001a\u0000t~\u00030\u0018\u0000u~\u0003 \u0010\u0000v~\u0003"+ - "\b\u0004\u0000w~\u00036\u001b\u0000x~\u00038\u001c\u0000y~\u0003<\u001e"+ - "\u0000z~\u0003>\u001f\u0000{~\u0003X,\u0000|~\u0003@ \u0000}p\u0001\u0000"+ - "\u0000\u0000}q\u0001\u0000\u0000\u0000}r\u0001\u0000\u0000\u0000}s\u0001"+ - "\u0000\u0000\u0000}t\u0001\u0000\u0000\u0000}u\u0001\u0000\u0000\u0000"+ - "}v\u0001\u0000\u0000\u0000}w\u0001\u0000\u0000\u0000}x\u0001\u0000\u0000"+ - "\u0000}y\u0001\u0000\u0000\u0000}z\u0001\u0000\u0000\u0000}{\u0001\u0000"+ - "\u0000\u0000}|\u0001\u0000\u0000\u0000~\u0007\u0001\u0000\u0000\u0000"+ - "\u007f\u0080\u0005\u0012\u0000\u0000\u0080\u0081\u0003\n\u0005\u0000\u0081"+ - "\t\u0001\u0000\u0000\u0000\u0082\u0083\u0006\u0005\uffff\uffff\u0000\u0083"+ - "\u0084\u0005+\u0000\u0000\u0084\u0098\u0003\n\u0005\u0006\u0085\u0098"+ - "\u0003\u000e\u0007\u0000\u0086\u0098\u0003\f\u0006\u0000\u0087\u0089\u0003"+ - "\u000e\u0007\u0000\u0088\u008a\u0005+\u0000\u0000\u0089\u0088\u0001\u0000"+ - "\u0000\u0000\u0089\u008a\u0001\u0000\u0000\u0000\u008a\u008b\u0001\u0000"+ - "\u0000\u0000\u008b\u008c\u0005)\u0000\u0000\u008c\u008d\u0005(\u0000\u0000"+ - "\u008d\u0092\u0003\u000e\u0007\u0000\u008e\u008f\u0005\"\u0000\u0000\u008f"+ - "\u0091\u0003\u000e\u0007\u0000\u0090\u008e\u0001\u0000\u0000\u0000\u0091"+ - "\u0094\u0001\u0000\u0000\u0000\u0092\u0090\u0001\u0000\u0000\u0000\u0092"+ - "\u0093\u0001\u0000\u0000\u0000\u0093\u0095\u0001\u0000\u0000\u0000\u0094"+ - "\u0092\u0001\u0000\u0000\u0000\u0095\u0096\u00051\u0000\u0000\u0096\u0098"+ - "\u0001\u0000\u0000\u0000\u0097\u0082\u0001\u0000\u0000\u0000\u0097\u0085"+ - "\u0001\u0000\u0000\u0000\u0097\u0086\u0001\u0000\u0000\u0000\u0097\u0087"+ - "\u0001\u0000\u0000\u0000\u0098\u00a1\u0001\u0000\u0000\u0000\u0099\u009a"+ - "\n\u0003\u0000\u0000\u009a\u009b\u0005\u001f\u0000\u0000\u009b\u00a0\u0003"+ - "\n\u0005\u0004\u009c\u009d\n\u0002\u0000\u0000\u009d\u009e\u0005.\u0000"+ - "\u0000\u009e\u00a0\u0003\n\u0005\u0003\u009f\u0099\u0001\u0000\u0000\u0000"+ - "\u009f\u009c\u0001\u0000\u0000\u0000\u00a0\u00a3\u0001\u0000\u0000\u0000"+ - "\u00a1\u009f\u0001\u0000\u0000\u0000\u00a1\u00a2\u0001\u0000\u0000\u0000"+ - "\u00a2\u000b\u0001\u0000\u0000\u0000\u00a3\u00a1\u0001\u0000\u0000\u0000"+ - "\u00a4\u00a6\u0003\u000e\u0007\u0000\u00a5\u00a7\u0005+\u0000\u0000\u00a6"+ - "\u00a5\u0001\u0000\u0000\u0000\u00a6\u00a7\u0001\u0000\u0000\u0000\u00a7"+ - "\u00a8\u0001\u0000\u0000\u0000\u00a8\u00a9\u0005*\u0000\u0000\u00a9\u00aa"+ - "\u0003N\'\u0000\u00aa\u00b3\u0001\u0000\u0000\u0000\u00ab\u00ad\u0003"+ - "\u000e\u0007\u0000\u00ac\u00ae\u0005+\u0000\u0000\u00ad\u00ac\u0001\u0000"+ - "\u0000\u0000\u00ad\u00ae\u0001\u0000\u0000\u0000\u00ae\u00af\u0001\u0000"+ - "\u0000\u0000\u00af\u00b0\u00050\u0000\u0000\u00b0\u00b1\u0003N\'\u0000"+ - "\u00b1\u00b3\u0001\u0000\u0000\u0000\u00b2\u00a4\u0001\u0000\u0000\u0000"+ - "\u00b2\u00ab\u0001\u0000\u0000\u0000\u00b3\r\u0001\u0000\u0000\u0000\u00b4"+ - "\u00ba\u0003\u0010\b\u0000\u00b5\u00b6\u0003\u0010\b\u0000\u00b6\u00b7"+ - "\u0003P(\u0000\u00b7\u00b8\u0003\u0010\b\u0000\u00b8\u00ba\u0001\u0000"+ - "\u0000\u0000\u00b9\u00b4\u0001\u0000\u0000\u0000\u00b9\u00b5\u0001\u0000"+ - "\u0000\u0000\u00ba\u000f\u0001\u0000\u0000\u0000\u00bb\u00bc\u0006\b\uffff"+ - "\uffff\u0000\u00bc\u00c0\u0003\u0012\t\u0000\u00bd\u00be\u0007\u0000\u0000"+ - "\u0000\u00be\u00c0\u0003\u0010\b\u0003\u00bf\u00bb\u0001\u0000\u0000\u0000"+ - "\u00bf\u00bd\u0001\u0000\u0000\u0000\u00c0\u00c9\u0001\u0000\u0000\u0000"+ - "\u00c1\u00c2\n\u0002\u0000\u0000\u00c2\u00c3\u0007\u0001\u0000\u0000\u00c3"+ - "\u00c8\u0003\u0010\b\u0003\u00c4\u00c5\n\u0001\u0000\u0000\u00c5\u00c6"+ - "\u0007\u0000\u0000\u0000\u00c6\u00c8\u0003\u0010\b\u0002\u00c7\u00c1\u0001"+ - "\u0000\u0000\u0000\u00c7\u00c4\u0001\u0000\u0000\u0000\u00c8\u00cb\u0001"+ - "\u0000\u0000\u0000\u00c9\u00c7\u0001\u0000\u0000\u0000\u00c9\u00ca\u0001"+ - "\u0000\u0000\u0000\u00ca\u0011\u0001\u0000\u0000\u0000\u00cb\u00c9\u0001"+ - "\u0000\u0000\u0000\u00cc\u00e1\u0003,\u0016\u0000\u00cd\u00e1\u0003(\u0014"+ - "\u0000\u00ce\u00cf\u0005(\u0000\u0000\u00cf\u00d0\u0003\n\u0005\u0000"+ - "\u00d0\u00d1\u00051\u0000\u0000\u00d1\u00e1\u0001\u0000\u0000\u0000\u00d2"+ - "\u00d3\u0003*\u0015\u0000\u00d3\u00dc\u0005(\u0000\u0000\u00d4\u00d9\u0003"+ - "\n\u0005\u0000\u00d5\u00d6\u0005\"\u0000\u0000\u00d6\u00d8\u0003\n\u0005"+ - "\u0000\u00d7\u00d5\u0001\u0000\u0000\u0000\u00d8\u00db\u0001\u0000\u0000"+ - "\u0000\u00d9\u00d7\u0001\u0000\u0000\u0000\u00d9\u00da\u0001\u0000\u0000"+ - "\u0000\u00da\u00dd\u0001\u0000\u0000\u0000\u00db\u00d9\u0001\u0000\u0000"+ - "\u0000\u00dc\u00d4\u0001\u0000\u0000\u0000\u00dc\u00dd\u0001\u0000\u0000"+ - "\u0000\u00dd\u00de\u0001\u0000\u0000\u0000\u00de\u00df\u00051\u0000\u0000"+ - "\u00df\u00e1\u0001\u0000\u0000\u0000\u00e0\u00cc\u0001\u0000\u0000\u0000"+ - "\u00e0\u00cd\u0001\u0000\u0000\u0000\u00e0\u00ce\u0001\u0000\u0000\u0000"+ - "\u00e0\u00d2\u0001\u0000\u0000\u0000\u00e1\u0013\u0001\u0000\u0000\u0000"+ - "\u00e2\u00e3\u0005\u000e\u0000\u0000\u00e3\u00e4\u0003\u0016\u000b\u0000"+ - "\u00e4\u0015\u0001\u0000\u0000\u0000\u00e5\u00ea\u0003\u0018\f\u0000\u00e6"+ - "\u00e7\u0005\"\u0000\u0000\u00e7\u00e9\u0003\u0018\f\u0000\u00e8\u00e6"+ - "\u0001\u0000\u0000\u0000\u00e9\u00ec\u0001\u0000\u0000\u0000\u00ea\u00e8"+ - "\u0001\u0000\u0000\u0000\u00ea\u00eb\u0001\u0000\u0000\u0000\u00eb\u0017"+ - "\u0001\u0000\u0000\u0000\u00ec\u00ea\u0001\u0000\u0000\u0000\u00ed\u00f3"+ - "\u0003\n\u0005\u0000\u00ee\u00ef\u0003(\u0014\u0000\u00ef\u00f0\u0005"+ - "!\u0000\u0000\u00f0\u00f1\u0003\n\u0005\u0000\u00f1\u00f3\u0001\u0000"+ - "\u0000\u0000\u00f2\u00ed\u0001\u0000\u0000\u0000\u00f2\u00ee\u0001\u0000"+ - "\u0000\u0000\u00f3\u0019\u0001\u0000\u0000\u0000\u00f4\u00f5\u0005\u0006"+ - "\u0000\u0000\u00f5\u00fa\u0003&\u0013\u0000\u00f6\u00f7\u0005\"\u0000"+ - "\u0000\u00f7\u00f9\u0003&\u0013\u0000\u00f8\u00f6\u0001\u0000\u0000\u0000"+ - "\u00f9\u00fc\u0001\u0000\u0000\u0000\u00fa\u00f8\u0001\u0000\u0000\u0000"+ - "\u00fa\u00fb\u0001\u0000\u0000\u0000\u00fb\u00fe\u0001\u0000\u0000\u0000"+ - "\u00fc\u00fa\u0001\u0000\u0000\u0000\u00fd\u00ff\u0003\u001c\u000e\u0000"+ - "\u00fe\u00fd\u0001\u0000\u0000\u0000\u00fe\u00ff\u0001\u0000\u0000\u0000"+ - "\u00ff\u001b\u0001\u0000\u0000\u0000\u0100\u0101\u0005@\u0000\u0000\u0101"+ - "\u0102\u0005H\u0000\u0000\u0102\u0107\u0003&\u0013\u0000\u0103\u0104\u0005"+ - "\"\u0000\u0000\u0104\u0106\u0003&\u0013\u0000\u0105\u0103\u0001\u0000"+ - "\u0000\u0000\u0106\u0109\u0001\u0000\u0000\u0000\u0107\u0105\u0001\u0000"+ - "\u0000\u0000\u0107\u0108\u0001\u0000\u0000\u0000\u0108\u010a\u0001\u0000"+ - "\u0000\u0000\u0109\u0107\u0001\u0000\u0000\u0000\u010a\u010b\u0005A\u0000"+ - "\u0000\u010b\u001d\u0001\u0000\u0000\u0000\u010c\u010d\u0005\u0004\u0000"+ - "\u0000\u010d\u010e\u0003\u0016\u000b\u0000\u010e\u001f\u0001\u0000\u0000"+ - "\u0000\u010f\u0111\u0005\u0011\u0000\u0000\u0110\u0112\u0003\u0016\u000b"+ - "\u0000\u0111\u0110\u0001\u0000\u0000\u0000\u0111\u0112\u0001\u0000\u0000"+ - "\u0000\u0112\u0115\u0001\u0000\u0000\u0000\u0113\u0114\u0005\u001e\u0000"+ - "\u0000\u0114\u0116\u0003$\u0012\u0000\u0115\u0113\u0001\u0000\u0000\u0000"+ - "\u0115\u0116\u0001\u0000\u0000\u0000\u0116!\u0001\u0000\u0000\u0000\u0117"+ - "\u0118\u0005\b\u0000\u0000\u0118\u011b\u0003\u0016\u000b\u0000\u0119\u011a"+ - "\u0005\u001e\u0000\u0000\u011a\u011c\u0003$\u0012\u0000\u011b\u0119\u0001"+ - "\u0000\u0000\u0000\u011b\u011c\u0001\u0000\u0000\u0000\u011c#\u0001\u0000"+ - "\u0000\u0000\u011d\u0122\u0003(\u0014\u0000\u011e\u011f\u0005\"\u0000"+ - "\u0000\u011f\u0121\u0003(\u0014\u0000\u0120\u011e\u0001\u0000\u0000\u0000"+ - "\u0121\u0124\u0001\u0000\u0000\u0000\u0122\u0120\u0001\u0000\u0000\u0000"+ - "\u0122\u0123\u0001\u0000\u0000\u0000\u0123%\u0001\u0000\u0000\u0000\u0124"+ - "\u0122\u0001\u0000\u0000\u0000\u0125\u0126\u0007\u0002\u0000\u0000\u0126"+ - "\'\u0001\u0000\u0000\u0000\u0127\u012c\u0003*\u0015\u0000\u0128\u0129"+ - "\u0005$\u0000\u0000\u0129\u012b\u0003*\u0015\u0000\u012a\u0128\u0001\u0000"+ - "\u0000\u0000\u012b\u012e\u0001\u0000\u0000\u0000\u012c\u012a\u0001\u0000"+ - "\u0000\u0000\u012c\u012d\u0001\u0000\u0000\u0000\u012d)\u0001\u0000\u0000"+ - "\u0000\u012e\u012c\u0001\u0000\u0000\u0000\u012f\u0130\u0007\u0003\u0000"+ - "\u0000\u0130+\u0001\u0000\u0000\u0000\u0131\u015c\u0005,\u0000\u0000\u0132"+ - "\u0133\u0003L&\u0000\u0133\u0134\u0005B\u0000\u0000\u0134\u015c\u0001"+ - "\u0000\u0000\u0000\u0135\u015c\u0003J%\u0000\u0136\u015c\u0003L&\u0000"+ - "\u0137\u015c\u0003F#\u0000\u0138\u015c\u0005/\u0000\u0000\u0139\u015c"+ - "\u0003N\'\u0000\u013a\u013b\u0005@\u0000\u0000\u013b\u0140\u0003H$\u0000"+ - "\u013c\u013d\u0005\"\u0000\u0000\u013d\u013f\u0003H$\u0000\u013e\u013c"+ - "\u0001\u0000\u0000\u0000\u013f\u0142\u0001\u0000\u0000\u0000\u0140\u013e"+ - "\u0001\u0000\u0000\u0000\u0140\u0141\u0001\u0000\u0000\u0000\u0141\u0143"+ - "\u0001\u0000\u0000\u0000\u0142\u0140\u0001\u0000\u0000\u0000\u0143\u0144"+ - "\u0005A\u0000\u0000\u0144\u015c\u0001\u0000\u0000\u0000\u0145\u0146\u0005"+ - "@\u0000\u0000\u0146\u014b\u0003F#\u0000\u0147\u0148\u0005\"\u0000\u0000"+ - "\u0148\u014a\u0003F#\u0000\u0149\u0147\u0001\u0000\u0000\u0000\u014a\u014d"+ - "\u0001\u0000\u0000\u0000\u014b\u0149\u0001\u0000\u0000\u0000\u014b\u014c"+ - "\u0001\u0000\u0000\u0000\u014c\u014e\u0001\u0000\u0000\u0000\u014d\u014b"+ - "\u0001\u0000\u0000\u0000\u014e\u014f\u0005A\u0000\u0000\u014f\u015c\u0001"+ - "\u0000\u0000\u0000\u0150\u0151\u0005@\u0000\u0000\u0151\u0156\u0003N\'"+ - "\u0000\u0152\u0153\u0005\"\u0000\u0000\u0153\u0155\u0003N\'\u0000\u0154"+ - "\u0152\u0001\u0000\u0000\u0000\u0155\u0158\u0001\u0000\u0000\u0000\u0156"+ - "\u0154\u0001\u0000\u0000\u0000\u0156\u0157\u0001\u0000\u0000\u0000\u0157"+ - "\u0159\u0001\u0000\u0000\u0000\u0158\u0156\u0001\u0000\u0000\u0000\u0159"+ - "\u015a\u0005A\u0000\u0000\u015a\u015c\u0001\u0000\u0000\u0000\u015b\u0131"+ - "\u0001\u0000\u0000\u0000\u015b\u0132\u0001\u0000\u0000\u0000\u015b\u0135"+ - "\u0001\u0000\u0000\u0000\u015b\u0136\u0001\u0000\u0000\u0000\u015b\u0137"+ - "\u0001\u0000\u0000\u0000\u015b\u0138\u0001\u0000\u0000\u0000\u015b\u0139"+ - "\u0001\u0000\u0000\u0000\u015b\u013a\u0001\u0000\u0000\u0000\u015b\u0145"+ - "\u0001\u0000\u0000\u0000\u015b\u0150\u0001\u0000\u0000\u0000\u015c-\u0001"+ - "\u0000\u0000\u0000\u015d\u015e\u0005\n\u0000\u0000\u015e\u015f\u0005\u001c"+ - "\u0000\u0000\u015f/\u0001\u0000\u0000\u0000\u0160\u0161\u0005\u0010\u0000"+ - "\u0000\u0161\u0166\u00032\u0019\u0000\u0162\u0163\u0005\"\u0000\u0000"+ - "\u0163\u0165\u00032\u0019\u0000\u0164\u0162\u0001\u0000\u0000\u0000\u0165"+ - "\u0168\u0001\u0000\u0000\u0000\u0166\u0164\u0001\u0000\u0000\u0000\u0166"+ - "\u0167\u0001\u0000\u0000\u0000\u01671\u0001\u0000\u0000\u0000\u0168\u0166"+ - "\u0001\u0000\u0000\u0000\u0169\u016b\u0003\n\u0005\u0000\u016a\u016c\u0007"+ - "\u0004\u0000\u0000\u016b\u016a\u0001\u0000\u0000\u0000\u016b\u016c\u0001"+ - "\u0000\u0000\u0000\u016c\u016f\u0001\u0000\u0000\u0000\u016d\u016e\u0005"+ - "-\u0000\u0000\u016e\u0170\u0007\u0005\u0000\u0000\u016f\u016d\u0001\u0000"+ - "\u0000\u0000\u016f\u0170\u0001\u0000\u0000\u0000\u01703\u0001\u0000\u0000"+ - "\u0000\u0171\u0172\u0005\t\u0000\u0000\u0172\u0177\u0003&\u0013\u0000"+ - "\u0173\u0174\u0005\"\u0000\u0000\u0174\u0176\u0003&\u0013\u0000\u0175"+ - "\u0173\u0001\u0000\u0000\u0000\u0176\u0179\u0001\u0000\u0000\u0000\u0177"+ - "\u0175\u0001\u0000\u0000\u0000\u0177\u0178\u0001\u0000\u0000\u0000\u0178"+ - "\u0184\u0001\u0000\u0000\u0000\u0179\u0177\u0001\u0000\u0000\u0000\u017a"+ - "\u017b\u0005\f\u0000\u0000\u017b\u0180\u0003&\u0013\u0000\u017c\u017d"+ - "\u0005\"\u0000\u0000\u017d\u017f\u0003&\u0013\u0000\u017e\u017c\u0001"+ - "\u0000\u0000\u0000\u017f\u0182\u0001\u0000\u0000\u0000\u0180\u017e\u0001"+ - "\u0000\u0000\u0000\u0180\u0181\u0001\u0000\u0000\u0000\u0181\u0184\u0001"+ - "\u0000\u0000\u0000\u0182\u0180\u0001\u0000\u0000\u0000\u0183\u0171\u0001"+ - "\u0000\u0000\u0000\u0183\u017a\u0001\u0000\u0000\u0000\u01845\u0001\u0000"+ - "\u0000\u0000\u0185\u0186\u0005\u0002\u0000\u0000\u0186\u018b\u0003&\u0013"+ - "\u0000\u0187\u0188\u0005\"\u0000\u0000\u0188\u018a\u0003&\u0013\u0000"+ - "\u0189\u0187\u0001\u0000\u0000\u0000\u018a\u018d\u0001\u0000\u0000\u0000"+ - "\u018b\u0189\u0001\u0000\u0000\u0000\u018b\u018c\u0001\u0000\u0000\u0000"+ - "\u018c7\u0001\u0000\u0000\u0000\u018d\u018b\u0001\u0000\u0000\u0000\u018e"+ - "\u018f\u0005\r\u0000\u0000\u018f\u0194\u0003:\u001d\u0000\u0190\u0191"+ - "\u0005\"\u0000\u0000\u0191\u0193\u0003:\u001d\u0000\u0192\u0190\u0001"+ - "\u0000\u0000\u0000\u0193\u0196\u0001\u0000\u0000\u0000\u0194\u0192\u0001"+ - "\u0000\u0000\u0000\u0194\u0195\u0001\u0000\u0000\u0000\u01959\u0001\u0000"+ - "\u0000\u0000\u0196\u0194\u0001\u0000\u0000\u0000\u0197\u0198\u0003&\u0013"+ - "\u0000\u0198\u0199\u0005G\u0000\u0000\u0199\u019a\u0003&\u0013\u0000\u019a"+ - ";\u0001\u0000\u0000\u0000\u019b\u019c\u0005\u0001\u0000\u0000\u019c\u019d"+ - "\u0003\u0012\t\u0000\u019d\u019f\u0003N\'\u0000\u019e\u01a0\u0003B!\u0000"+ - "\u019f\u019e\u0001\u0000\u0000\u0000\u019f\u01a0\u0001\u0000\u0000\u0000"+ - "\u01a0=\u0001\u0000\u0000\u0000\u01a1\u01a2\u0005\u0007\u0000\u0000\u01a2"+ - "\u01a3\u0003\u0012\t\u0000\u01a3\u01a4\u0003N\'\u0000\u01a4?\u0001\u0000"+ - "\u0000\u0000\u01a5\u01a6\u0005\u000b\u0000\u0000\u01a6\u01a7\u0003&\u0013"+ - "\u0000\u01a7A\u0001\u0000\u0000\u0000\u01a8\u01ad\u0003D\"\u0000\u01a9"+ - "\u01aa\u0005\"\u0000\u0000\u01aa\u01ac\u0003D\"\u0000\u01ab\u01a9\u0001"+ - "\u0000\u0000\u0000\u01ac\u01af\u0001\u0000\u0000\u0000\u01ad\u01ab\u0001"+ - "\u0000\u0000\u0000\u01ad\u01ae\u0001\u0000\u0000\u0000\u01aeC\u0001\u0000"+ - "\u0000\u0000\u01af\u01ad\u0001\u0000\u0000\u0000\u01b0\u01b1\u0003*\u0015"+ - "\u0000\u01b1\u01b2\u0005!\u0000\u0000\u01b2\u01b3\u0003,\u0016\u0000\u01b3"+ - "E\u0001\u0000\u0000\u0000\u01b4\u01b5\u0007\u0006\u0000\u0000\u01b5G\u0001"+ - "\u0000\u0000\u0000\u01b6\u01b9\u0003J%\u0000\u01b7\u01b9\u0003L&\u0000"+ - "\u01b8\u01b6\u0001\u0000\u0000\u0000\u01b8\u01b7\u0001\u0000\u0000\u0000"+ - "\u01b9I\u0001\u0000\u0000\u0000\u01ba\u01bc\u0007\u0000\u0000\u0000\u01bb"+ - "\u01ba\u0001\u0000\u0000\u0000\u01bb\u01bc\u0001\u0000\u0000\u0000\u01bc"+ - "\u01bd\u0001\u0000\u0000\u0000\u01bd\u01be\u0005\u001d\u0000\u0000\u01be"+ - "K\u0001\u0000\u0000\u0000\u01bf\u01c1\u0007\u0000\u0000\u0000\u01c0\u01bf"+ - "\u0001\u0000\u0000\u0000\u01c0\u01c1\u0001\u0000\u0000\u0000\u01c1\u01c2"+ - "\u0001\u0000\u0000\u0000\u01c2\u01c3\u0005\u001c\u0000\u0000\u01c3M\u0001"+ - "\u0000\u0000\u0000\u01c4\u01c5\u0005\u001b\u0000\u0000\u01c5O\u0001\u0000"+ - "\u0000\u0000\u01c6\u01c7\u0007\u0007\u0000\u0000\u01c7Q\u0001\u0000\u0000"+ - "\u0000\u01c8\u01c9\u0005\u0005\u0000\u0000\u01c9\u01ca\u0003T*\u0000\u01ca"+ - "S\u0001\u0000\u0000\u0000\u01cb\u01cc\u0005@\u0000\u0000\u01cc\u01cd\u0003"+ - "\u0002\u0001\u0000\u01cd\u01ce\u0005A\u0000\u0000\u01ceU\u0001\u0000\u0000"+ - "\u0000\u01cf\u01d0\u0005\u000f\u0000\u0000\u01d0\u01d4\u00053\u0000\u0000"+ - "\u01d1\u01d2\u0005\u000f\u0000\u0000\u01d2\u01d4\u00054\u0000\u0000\u01d3"+ - "\u01cf\u0001\u0000\u0000\u0000\u01d3\u01d1\u0001\u0000\u0000\u0000\u01d4"+ - "W\u0001\u0000\u0000\u0000\u01d5\u01d6\u0005\u0003\u0000\u0000\u01d6\u01d9"+ - "\u0003&\u0013\u0000\u01d7\u01d8\u0005I\u0000\u0000\u01d8\u01da\u0003&"+ - "\u0013\u0000\u01d9\u01d7\u0001\u0000\u0000\u0000\u01d9\u01da\u0001\u0000"+ - "\u0000\u0000\u01da\u01e4\u0001\u0000\u0000\u0000\u01db\u01dc\u0005J\u0000"+ - "\u0000\u01dc\u01e1\u0003Z-\u0000\u01dd\u01de\u0005\"\u0000\u0000\u01de"+ - "\u01e0\u0003Z-\u0000\u01df\u01dd\u0001\u0000\u0000\u0000\u01e0\u01e3\u0001"+ - "\u0000\u0000\u0000\u01e1\u01df\u0001\u0000\u0000\u0000\u01e1\u01e2\u0001"+ - "\u0000\u0000\u0000\u01e2\u01e5\u0001\u0000\u0000\u0000\u01e3\u01e1\u0001"+ - "\u0000\u0000\u0000\u01e4\u01db\u0001\u0000\u0000\u0000\u01e4\u01e5\u0001"+ - "\u0000\u0000\u0000\u01e5Y\u0001\u0000\u0000\u0000\u01e6\u01e7\u0003&\u0013"+ - "\u0000\u01e7\u01e8\u0005!\u0000\u0000\u01e8\u01ea\u0001\u0000\u0000\u0000"+ - "\u01e9\u01e6\u0001\u0000\u0000\u0000\u01e9\u01ea\u0001\u0000\u0000\u0000"+ - "\u01ea\u01eb\u0001\u0000\u0000\u0000\u01eb\u01ec\u0003&\u0013\u0000\u01ec"+ - "[\u0001\u0000\u0000\u00002gn}\u0089\u0092\u0097\u009f\u00a1\u00a6\u00ad"+ - "\u00b2\u00b9\u00bf\u00c7\u00c9\u00d9\u00dc\u00e0\u00ea\u00f2\u00fa\u00fe"+ - "\u0107\u0111\u0115\u011b\u0122\u012c\u0140\u014b\u0156\u015b\u0166\u016b"+ - "\u016f\u0177\u0180\u0183\u018b\u0194\u019f\u01ad\u01b8\u01bb\u01c0\u01d3"+ - "\u01d9\u01e1\u01e4\u01e9"; + "\u0016\u0151\b\u0016\n\u0016\f\u0016\u0154\t\u0016\u0001\u0016\u0001\u0016"+ + "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0005\u0016\u015c\b\u0016"+ + "\n\u0016\f\u0016\u015f\t\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u0163"+ + "\b\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001"+ + "\u0018\u0001\u0018\u0005\u0018\u016c\b\u0018\n\u0018\f\u0018\u016f\t\u0018"+ + "\u0001\u0019\u0001\u0019\u0003\u0019\u0173\b\u0019\u0001\u0019\u0001\u0019"+ + "\u0003\u0019\u0177\b\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a"+ + "\u0005\u001a\u017d\b\u001a\n\u001a\f\u001a\u0180\t\u001a\u0001\u001a\u0001"+ + "\u001a\u0001\u001a\u0001\u001a\u0005\u001a\u0186\b\u001a\n\u001a\f\u001a"+ + "\u0189\t\u001a\u0003\u001a\u018b\b\u001a\u0001\u001b\u0001\u001b\u0001"+ + "\u001b\u0001\u001b\u0005\u001b\u0191\b\u001b\n\u001b\f\u001b\u0194\t\u001b"+ + "\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0005\u001c\u019a\b\u001c"+ + "\n\u001c\f\u001c\u019d\t\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001"+ + "\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0003\u001e\u01a7"+ + "\b\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0001"+ + " \u0001 \u0001!\u0001!\u0001!\u0005!\u01b3\b!\n!\f!\u01b6\t!\u0001\"\u0001"+ + "\"\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0003$\u01c0\b$\u0001%"+ + "\u0003%\u01c3\b%\u0001%\u0001%\u0001&\u0003&\u01c8\b&\u0001&\u0001&\u0001"+ + "\'\u0001\'\u0001(\u0001(\u0001)\u0001)\u0001)\u0001*\u0001*\u0001*\u0001"+ + "*\u0001+\u0001+\u0001+\u0001+\u0003+\u01db\b+\u0001,\u0001,\u0001,\u0001"+ + ",\u0003,\u01e1\b,\u0001,\u0001,\u0001,\u0001,\u0005,\u01e7\b,\n,\f,\u01ea"+ + "\t,\u0003,\u01ec\b,\u0001-\u0001-\u0001-\u0003-\u01f1\b-\u0001-\u0001"+ + "-\u0001-\u0000\u0003\u0002\n\u0010.\u0000\u0002\u0004\u0006\b\n\f\u000e"+ + "\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDF"+ + "HJLNPRTVXZ\u0000\b\u0001\u0000<=\u0001\u0000>@\u0001\u0000LM\u0001\u0000"+ + "CD\u0002\u0000 ##\u0001\u0000&\'\u0002\u0000%%33\u0001\u00006;\u0213"+ + "\u0000\\\u0001\u0000\u0000\u0000\u0002_\u0001\u0000\u0000\u0000\u0004"+ + "n\u0001\u0000\u0000\u0000\u0006}\u0001\u0000\u0000\u0000\b\u007f\u0001"+ + "\u0000\u0000\u0000\n\u009e\u0001\u0000\u0000\u0000\f\u00b9\u0001\u0000"+ + "\u0000\u0000\u000e\u00c0\u0001\u0000\u0000\u0000\u0010\u00c6\u0001\u0000"+ + "\u0000\u0000\u0012\u00e7\u0001\u0000\u0000\u0000\u0014\u00e9\u0001\u0000"+ + "\u0000\u0000\u0016\u00ec\u0001\u0000\u0000\u0000\u0018\u00f9\u0001\u0000"+ + "\u0000\u0000\u001a\u00fb\u0001\u0000\u0000\u0000\u001c\u0107\u0001\u0000"+ + "\u0000\u0000\u001e\u0113\u0001\u0000\u0000\u0000 \u0116\u0001\u0000\u0000"+ + "\u0000\"\u011e\u0001\u0000\u0000\u0000$\u0124\u0001\u0000\u0000\u0000"+ + "&\u012c\u0001\u0000\u0000\u0000(\u012e\u0001\u0000\u0000\u0000*\u0136"+ + "\u0001\u0000\u0000\u0000,\u0162\u0001\u0000\u0000\u0000.\u0164\u0001\u0000"+ + "\u0000\u00000\u0167\u0001\u0000\u0000\u00002\u0170\u0001\u0000\u0000\u0000"+ + "4\u018a\u0001\u0000\u0000\u00006\u018c\u0001\u0000\u0000\u00008\u0195"+ + "\u0001\u0000\u0000\u0000:\u019e\u0001\u0000\u0000\u0000<\u01a2\u0001\u0000"+ + "\u0000\u0000>\u01a8\u0001\u0000\u0000\u0000@\u01ac\u0001\u0000\u0000\u0000"+ + "B\u01af\u0001\u0000\u0000\u0000D\u01b7\u0001\u0000\u0000\u0000F\u01bb"+ + "\u0001\u0000\u0000\u0000H\u01bf\u0001\u0000\u0000\u0000J\u01c2\u0001\u0000"+ + "\u0000\u0000L\u01c7\u0001\u0000\u0000\u0000N\u01cb\u0001\u0000\u0000\u0000"+ + "P\u01cd\u0001\u0000\u0000\u0000R\u01cf\u0001\u0000\u0000\u0000T\u01d2"+ + "\u0001\u0000\u0000\u0000V\u01da\u0001\u0000\u0000\u0000X\u01dc\u0001\u0000"+ + "\u0000\u0000Z\u01f0\u0001\u0000\u0000\u0000\\]\u0003\u0002\u0001\u0000"+ + "]^\u0005\u0000\u0000\u0001^\u0001\u0001\u0000\u0000\u0000_`\u0006\u0001"+ + "\uffff\uffff\u0000`a\u0003\u0004\u0002\u0000ag\u0001\u0000\u0000\u0000"+ + "bc\n\u0001\u0000\u0000cd\u0005\u001a\u0000\u0000df\u0003\u0006\u0003\u0000"+ + "eb\u0001\u0000\u0000\u0000fi\u0001\u0000\u0000\u0000ge\u0001\u0000\u0000"+ + "\u0000gh\u0001\u0000\u0000\u0000h\u0003\u0001\u0000\u0000\u0000ig\u0001"+ + "\u0000\u0000\u0000jo\u0003R)\u0000ko\u0003\u001a\r\u0000lo\u0003\u0014"+ + "\n\u0000mo\u0003V+\u0000nj\u0001\u0000\u0000\u0000nk\u0001\u0000\u0000"+ + "\u0000nl\u0001\u0000\u0000\u0000nm\u0001\u0000\u0000\u0000o\u0005\u0001"+ + "\u0000\u0000\u0000p~\u0003\u001e\u000f\u0000q~\u0003\"\u0011\u0000r~\u0003"+ + ".\u0017\u0000s~\u00034\u001a\u0000t~\u00030\u0018\u0000u~\u0003 \u0010"+ + "\u0000v~\u0003\b\u0004\u0000w~\u00036\u001b\u0000x~\u00038\u001c\u0000"+ + "y~\u0003<\u001e\u0000z~\u0003>\u001f\u0000{~\u0003X,\u0000|~\u0003@ \u0000"+ + "}p\u0001\u0000\u0000\u0000}q\u0001\u0000\u0000\u0000}r\u0001\u0000\u0000"+ + "\u0000}s\u0001\u0000\u0000\u0000}t\u0001\u0000\u0000\u0000}u\u0001\u0000"+ + "\u0000\u0000}v\u0001\u0000\u0000\u0000}w\u0001\u0000\u0000\u0000}x\u0001"+ + "\u0000\u0000\u0000}y\u0001\u0000\u0000\u0000}z\u0001\u0000\u0000\u0000"+ + "}{\u0001\u0000\u0000\u0000}|\u0001\u0000\u0000\u0000~\u0007\u0001\u0000"+ + "\u0000\u0000\u007f\u0080\u0005\u0012\u0000\u0000\u0080\u0081\u0003\n\u0005"+ + "\u0000\u0081\t\u0001\u0000\u0000\u0000\u0082\u0083\u0006\u0005\uffff\uffff"+ + "\u0000\u0083\u0084\u0005,\u0000\u0000\u0084\u009f\u0003\n\u0005\u0007"+ + "\u0085\u009f\u0003\u000e\u0007\u0000\u0086\u009f\u0003\f\u0006\u0000\u0087"+ + "\u0089\u0003\u000e\u0007\u0000\u0088\u008a\u0005,\u0000\u0000\u0089\u0088"+ + "\u0001\u0000\u0000\u0000\u0089\u008a\u0001\u0000\u0000\u0000\u008a\u008b"+ + "\u0001\u0000\u0000\u0000\u008b\u008c\u0005)\u0000\u0000\u008c\u008d\u0005"+ + "(\u0000\u0000\u008d\u0092\u0003\u000e\u0007\u0000\u008e\u008f\u0005\""+ + "\u0000\u0000\u008f\u0091\u0003\u000e\u0007\u0000\u0090\u008e\u0001\u0000"+ + "\u0000\u0000\u0091\u0094\u0001\u0000\u0000\u0000\u0092\u0090\u0001\u0000"+ + "\u0000\u0000\u0092\u0093\u0001\u0000\u0000\u0000\u0093\u0095\u0001\u0000"+ + "\u0000\u0000\u0094\u0092\u0001\u0000\u0000\u0000\u0095\u0096\u00052\u0000"+ + "\u0000\u0096\u009f\u0001\u0000\u0000\u0000\u0097\u0098\u0003\u000e\u0007"+ + "\u0000\u0098\u009a\u0005*\u0000\u0000\u0099\u009b\u0005,\u0000\u0000\u009a"+ + "\u0099\u0001\u0000\u0000\u0000\u009a\u009b\u0001\u0000\u0000\u0000\u009b"+ + "\u009c\u0001\u0000\u0000\u0000\u009c\u009d\u0005-\u0000\u0000\u009d\u009f"+ + "\u0001\u0000\u0000\u0000\u009e\u0082\u0001\u0000\u0000\u0000\u009e\u0085"+ + "\u0001\u0000\u0000\u0000\u009e\u0086\u0001\u0000\u0000\u0000\u009e\u0087"+ + "\u0001\u0000\u0000\u0000\u009e\u0097\u0001\u0000\u0000\u0000\u009f\u00a8"+ + "\u0001\u0000\u0000\u0000\u00a0\u00a1\n\u0004\u0000\u0000\u00a1\u00a2\u0005"+ + "\u001f\u0000\u0000\u00a2\u00a7\u0003\n\u0005\u0005\u00a3\u00a4\n\u0003"+ + "\u0000\u0000\u00a4\u00a5\u0005/\u0000\u0000\u00a5\u00a7\u0003\n\u0005"+ + "\u0004\u00a6\u00a0\u0001\u0000\u0000\u0000\u00a6\u00a3\u0001\u0000\u0000"+ + "\u0000\u00a7\u00aa\u0001\u0000\u0000\u0000\u00a8\u00a6\u0001\u0000\u0000"+ + "\u0000\u00a8\u00a9\u0001\u0000\u0000\u0000\u00a9\u000b\u0001\u0000\u0000"+ + "\u0000\u00aa\u00a8\u0001\u0000\u0000\u0000\u00ab\u00ad\u0003\u000e\u0007"+ + "\u0000\u00ac\u00ae\u0005,\u0000\u0000\u00ad\u00ac\u0001\u0000\u0000\u0000"+ + "\u00ad\u00ae\u0001\u0000\u0000\u0000\u00ae\u00af\u0001\u0000\u0000\u0000"+ + "\u00af\u00b0\u0005+\u0000\u0000\u00b0\u00b1\u0003N\'\u0000\u00b1\u00ba"+ + "\u0001\u0000\u0000\u0000\u00b2\u00b4\u0003\u000e\u0007\u0000\u00b3\u00b5"+ + "\u0005,\u0000\u0000\u00b4\u00b3\u0001\u0000\u0000\u0000\u00b4\u00b5\u0001"+ + "\u0000\u0000\u0000\u00b5\u00b6\u0001\u0000\u0000\u0000\u00b6\u00b7\u0005"+ + "1\u0000\u0000\u00b7\u00b8\u0003N\'\u0000\u00b8\u00ba\u0001\u0000\u0000"+ + "\u0000\u00b9\u00ab\u0001\u0000\u0000\u0000\u00b9\u00b2\u0001\u0000\u0000"+ + "\u0000\u00ba\r\u0001\u0000\u0000\u0000\u00bb\u00c1\u0003\u0010\b\u0000"+ + "\u00bc\u00bd\u0003\u0010\b\u0000\u00bd\u00be\u0003P(\u0000\u00be\u00bf"+ + "\u0003\u0010\b\u0000\u00bf\u00c1\u0001\u0000\u0000\u0000\u00c0\u00bb\u0001"+ + "\u0000\u0000\u0000\u00c0\u00bc\u0001\u0000\u0000\u0000\u00c1\u000f\u0001"+ + "\u0000\u0000\u0000\u00c2\u00c3\u0006\b\uffff\uffff\u0000\u00c3\u00c7\u0003"+ + "\u0012\t\u0000\u00c4\u00c5\u0007\u0000\u0000\u0000\u00c5\u00c7\u0003\u0010"+ + "\b\u0003\u00c6\u00c2\u0001\u0000\u0000\u0000\u00c6\u00c4\u0001\u0000\u0000"+ + "\u0000\u00c7\u00d0\u0001\u0000\u0000\u0000\u00c8\u00c9\n\u0002\u0000\u0000"+ + "\u00c9\u00ca\u0007\u0001\u0000\u0000\u00ca\u00cf\u0003\u0010\b\u0003\u00cb"+ + "\u00cc\n\u0001\u0000\u0000\u00cc\u00cd\u0007\u0000\u0000\u0000\u00cd\u00cf"+ + "\u0003\u0010\b\u0002\u00ce\u00c8\u0001\u0000\u0000\u0000\u00ce\u00cb\u0001"+ + "\u0000\u0000\u0000\u00cf\u00d2\u0001\u0000\u0000\u0000\u00d0\u00ce\u0001"+ + "\u0000\u0000\u0000\u00d0\u00d1\u0001\u0000\u0000\u0000\u00d1\u0011\u0001"+ + "\u0000\u0000\u0000\u00d2\u00d0\u0001\u0000\u0000\u0000\u00d3\u00e8\u0003"+ + ",\u0016\u0000\u00d4\u00e8\u0003(\u0014\u0000\u00d5\u00d6\u0005(\u0000"+ + "\u0000\u00d6\u00d7\u0003\n\u0005\u0000\u00d7\u00d8\u00052\u0000\u0000"+ + "\u00d8\u00e8\u0001\u0000\u0000\u0000\u00d9\u00da\u0003*\u0015\u0000\u00da"+ + "\u00e3\u0005(\u0000\u0000\u00db\u00e0\u0003\n\u0005\u0000\u00dc\u00dd"+ + "\u0005\"\u0000\u0000\u00dd\u00df\u0003\n\u0005\u0000\u00de\u00dc\u0001"+ + "\u0000\u0000\u0000\u00df\u00e2\u0001\u0000\u0000\u0000\u00e0\u00de\u0001"+ + "\u0000\u0000\u0000\u00e0\u00e1\u0001\u0000\u0000\u0000\u00e1\u00e4\u0001"+ + "\u0000\u0000\u0000\u00e2\u00e0\u0001\u0000\u0000\u0000\u00e3\u00db\u0001"+ + "\u0000\u0000\u0000\u00e3\u00e4\u0001\u0000\u0000\u0000\u00e4\u00e5\u0001"+ + "\u0000\u0000\u0000\u00e5\u00e6\u00052\u0000\u0000\u00e6\u00e8\u0001\u0000"+ + "\u0000\u0000\u00e7\u00d3\u0001\u0000\u0000\u0000\u00e7\u00d4\u0001\u0000"+ + "\u0000\u0000\u00e7\u00d5\u0001\u0000\u0000\u0000\u00e7\u00d9\u0001\u0000"+ + "\u0000\u0000\u00e8\u0013\u0001\u0000\u0000\u0000\u00e9\u00ea\u0005\u000e"+ + "\u0000\u0000\u00ea\u00eb\u0003\u0016\u000b\u0000\u00eb\u0015\u0001\u0000"+ + "\u0000\u0000\u00ec\u00f1\u0003\u0018\f\u0000\u00ed\u00ee\u0005\"\u0000"+ + "\u0000\u00ee\u00f0\u0003\u0018\f\u0000\u00ef\u00ed\u0001\u0000\u0000\u0000"+ + "\u00f0\u00f3\u0001\u0000\u0000\u0000\u00f1\u00ef\u0001\u0000\u0000\u0000"+ + "\u00f1\u00f2\u0001\u0000\u0000\u0000\u00f2\u0017\u0001\u0000\u0000\u0000"+ + "\u00f3\u00f1\u0001\u0000\u0000\u0000\u00f4\u00fa\u0003\n\u0005\u0000\u00f5"+ + "\u00f6\u0003(\u0014\u0000\u00f6\u00f7\u0005!\u0000\u0000\u00f7\u00f8\u0003"+ + "\n\u0005\u0000\u00f8\u00fa\u0001\u0000\u0000\u0000\u00f9\u00f4\u0001\u0000"+ + "\u0000\u0000\u00f9\u00f5\u0001\u0000\u0000\u0000\u00fa\u0019\u0001\u0000"+ + "\u0000\u0000\u00fb\u00fc\u0005\u0006\u0000\u0000\u00fc\u0101\u0003&\u0013"+ + "\u0000\u00fd\u00fe\u0005\"\u0000\u0000\u00fe\u0100\u0003&\u0013\u0000"+ + "\u00ff\u00fd\u0001\u0000\u0000\u0000\u0100\u0103\u0001\u0000\u0000\u0000"+ + "\u0101\u00ff\u0001\u0000\u0000\u0000\u0101\u0102\u0001\u0000\u0000\u0000"+ + "\u0102\u0105\u0001\u0000\u0000\u0000\u0103\u0101\u0001\u0000\u0000\u0000"+ + "\u0104\u0106\u0003\u001c\u000e\u0000\u0105\u0104\u0001\u0000\u0000\u0000"+ + "\u0105\u0106\u0001\u0000\u0000\u0000\u0106\u001b\u0001\u0000\u0000\u0000"+ + "\u0107\u0108\u0005A\u0000\u0000\u0108\u0109\u0005I\u0000\u0000\u0109\u010e"+ + "\u0003&\u0013\u0000\u010a\u010b\u0005\"\u0000\u0000\u010b\u010d\u0003"+ + "&\u0013\u0000\u010c\u010a\u0001\u0000\u0000\u0000\u010d\u0110\u0001\u0000"+ + "\u0000\u0000\u010e\u010c\u0001\u0000\u0000\u0000\u010e\u010f\u0001\u0000"+ + "\u0000\u0000\u010f\u0111\u0001\u0000\u0000\u0000\u0110\u010e\u0001\u0000"+ + "\u0000\u0000\u0111\u0112\u0005B\u0000\u0000\u0112\u001d\u0001\u0000\u0000"+ + "\u0000\u0113\u0114\u0005\u0004\u0000\u0000\u0114\u0115\u0003\u0016\u000b"+ + "\u0000\u0115\u001f\u0001\u0000\u0000\u0000\u0116\u0118\u0005\u0011\u0000"+ + "\u0000\u0117\u0119\u0003\u0016\u000b\u0000\u0118\u0117\u0001\u0000\u0000"+ + "\u0000\u0118\u0119\u0001\u0000\u0000\u0000\u0119\u011c\u0001\u0000\u0000"+ + "\u0000\u011a\u011b\u0005\u001e\u0000\u0000\u011b\u011d\u0003$\u0012\u0000"+ + "\u011c\u011a\u0001\u0000\u0000\u0000\u011c\u011d\u0001\u0000\u0000\u0000"+ + "\u011d!\u0001\u0000\u0000\u0000\u011e\u011f\u0005\b\u0000\u0000\u011f"+ + "\u0122\u0003\u0016\u000b\u0000\u0120\u0121\u0005\u001e\u0000\u0000\u0121"+ + "\u0123\u0003$\u0012\u0000\u0122\u0120\u0001\u0000\u0000\u0000\u0122\u0123"+ + "\u0001\u0000\u0000\u0000\u0123#\u0001\u0000\u0000\u0000\u0124\u0129\u0003"+ + "(\u0014\u0000\u0125\u0126\u0005\"\u0000\u0000\u0126\u0128\u0003(\u0014"+ + "\u0000\u0127\u0125\u0001\u0000\u0000\u0000\u0128\u012b\u0001\u0000\u0000"+ + "\u0000\u0129\u0127\u0001\u0000\u0000\u0000\u0129\u012a\u0001\u0000\u0000"+ + "\u0000\u012a%\u0001\u0000\u0000\u0000\u012b\u0129\u0001\u0000\u0000\u0000"+ + "\u012c\u012d\u0007\u0002\u0000\u0000\u012d\'\u0001\u0000\u0000\u0000\u012e"+ + "\u0133\u0003*\u0015\u0000\u012f\u0130\u0005$\u0000\u0000\u0130\u0132\u0003"+ + "*\u0015\u0000\u0131\u012f\u0001\u0000\u0000\u0000\u0132\u0135\u0001\u0000"+ + "\u0000\u0000\u0133\u0131\u0001\u0000\u0000\u0000\u0133\u0134\u0001\u0000"+ + "\u0000\u0000\u0134)\u0001\u0000\u0000\u0000\u0135\u0133\u0001\u0000\u0000"+ + "\u0000\u0136\u0137\u0007\u0003\u0000\u0000\u0137+\u0001\u0000\u0000\u0000"+ + "\u0138\u0163\u0005-\u0000\u0000\u0139\u013a\u0003L&\u0000\u013a\u013b"+ + "\u0005C\u0000\u0000\u013b\u0163\u0001\u0000\u0000\u0000\u013c\u0163\u0003"+ + "J%\u0000\u013d\u0163\u0003L&\u0000\u013e\u0163\u0003F#\u0000\u013f\u0163"+ + "\u00050\u0000\u0000\u0140\u0163\u0003N\'\u0000\u0141\u0142\u0005A\u0000"+ + "\u0000\u0142\u0147\u0003H$\u0000\u0143\u0144\u0005\"\u0000\u0000\u0144"+ + "\u0146\u0003H$\u0000\u0145\u0143\u0001\u0000\u0000\u0000\u0146\u0149\u0001"+ + "\u0000\u0000\u0000\u0147\u0145\u0001\u0000\u0000\u0000\u0147\u0148\u0001"+ + "\u0000\u0000\u0000\u0148\u014a\u0001\u0000\u0000\u0000\u0149\u0147\u0001"+ + "\u0000\u0000\u0000\u014a\u014b\u0005B\u0000\u0000\u014b\u0163\u0001\u0000"+ + "\u0000\u0000\u014c\u014d\u0005A\u0000\u0000\u014d\u0152\u0003F#\u0000"+ + "\u014e\u014f\u0005\"\u0000\u0000\u014f\u0151\u0003F#\u0000\u0150\u014e"+ + "\u0001\u0000\u0000\u0000\u0151\u0154\u0001\u0000\u0000\u0000\u0152\u0150"+ + "\u0001\u0000\u0000\u0000\u0152\u0153\u0001\u0000\u0000\u0000\u0153\u0155"+ + "\u0001\u0000\u0000\u0000\u0154\u0152\u0001\u0000\u0000\u0000\u0155\u0156"+ + "\u0005B\u0000\u0000\u0156\u0163\u0001\u0000\u0000\u0000\u0157\u0158\u0005"+ + "A\u0000\u0000\u0158\u015d\u0003N\'\u0000\u0159\u015a\u0005\"\u0000\u0000"+ + "\u015a\u015c\u0003N\'\u0000\u015b\u0159\u0001\u0000\u0000\u0000\u015c"+ + "\u015f\u0001\u0000\u0000\u0000\u015d\u015b\u0001\u0000\u0000\u0000\u015d"+ + "\u015e\u0001\u0000\u0000\u0000\u015e\u0160\u0001\u0000\u0000\u0000\u015f"+ + "\u015d\u0001\u0000\u0000\u0000\u0160\u0161\u0005B\u0000\u0000\u0161\u0163"+ + "\u0001\u0000\u0000\u0000\u0162\u0138\u0001\u0000\u0000\u0000\u0162\u0139"+ + "\u0001\u0000\u0000\u0000\u0162\u013c\u0001\u0000\u0000\u0000\u0162\u013d"+ + "\u0001\u0000\u0000\u0000\u0162\u013e\u0001\u0000\u0000\u0000\u0162\u013f"+ + "\u0001\u0000\u0000\u0000\u0162\u0140\u0001\u0000\u0000\u0000\u0162\u0141"+ + "\u0001\u0000\u0000\u0000\u0162\u014c\u0001\u0000\u0000\u0000\u0162\u0157"+ + "\u0001\u0000\u0000\u0000\u0163-\u0001\u0000\u0000\u0000\u0164\u0165\u0005"+ + "\n\u0000\u0000\u0165\u0166\u0005\u001c\u0000\u0000\u0166/\u0001\u0000"+ + "\u0000\u0000\u0167\u0168\u0005\u0010\u0000\u0000\u0168\u016d\u00032\u0019"+ + "\u0000\u0169\u016a\u0005\"\u0000\u0000\u016a\u016c\u00032\u0019\u0000"+ + "\u016b\u0169\u0001\u0000\u0000\u0000\u016c\u016f\u0001\u0000\u0000\u0000"+ + "\u016d\u016b\u0001\u0000\u0000\u0000\u016d\u016e\u0001\u0000\u0000\u0000"+ + "\u016e1\u0001\u0000\u0000\u0000\u016f\u016d\u0001\u0000\u0000\u0000\u0170"+ + "\u0172\u0003\n\u0005\u0000\u0171\u0173\u0007\u0004\u0000\u0000\u0172\u0171"+ + "\u0001\u0000\u0000\u0000\u0172\u0173\u0001\u0000\u0000\u0000\u0173\u0176"+ + "\u0001\u0000\u0000\u0000\u0174\u0175\u0005.\u0000\u0000\u0175\u0177\u0007"+ + "\u0005\u0000\u0000\u0176\u0174\u0001\u0000\u0000\u0000\u0176\u0177\u0001"+ + "\u0000\u0000\u0000\u01773\u0001\u0000\u0000\u0000\u0178\u0179\u0005\t"+ + "\u0000\u0000\u0179\u017e\u0003&\u0013\u0000\u017a\u017b\u0005\"\u0000"+ + "\u0000\u017b\u017d\u0003&\u0013\u0000\u017c\u017a\u0001\u0000\u0000\u0000"+ + "\u017d\u0180\u0001\u0000\u0000\u0000\u017e\u017c\u0001\u0000\u0000\u0000"+ + "\u017e\u017f\u0001\u0000\u0000\u0000\u017f\u018b\u0001\u0000\u0000\u0000"+ + "\u0180\u017e\u0001\u0000\u0000\u0000\u0181\u0182\u0005\f\u0000\u0000\u0182"+ + "\u0187\u0003&\u0013\u0000\u0183\u0184\u0005\"\u0000\u0000\u0184\u0186"+ + "\u0003&\u0013\u0000\u0185\u0183\u0001\u0000\u0000\u0000\u0186\u0189\u0001"+ + "\u0000\u0000\u0000\u0187\u0185\u0001\u0000\u0000\u0000\u0187\u0188\u0001"+ + "\u0000\u0000\u0000\u0188\u018b\u0001\u0000\u0000\u0000\u0189\u0187\u0001"+ + "\u0000\u0000\u0000\u018a\u0178\u0001\u0000\u0000\u0000\u018a\u0181\u0001"+ + "\u0000\u0000\u0000\u018b5\u0001\u0000\u0000\u0000\u018c\u018d\u0005\u0002"+ + "\u0000\u0000\u018d\u0192\u0003&\u0013\u0000\u018e\u018f\u0005\"\u0000"+ + "\u0000\u018f\u0191\u0003&\u0013\u0000\u0190\u018e\u0001\u0000\u0000\u0000"+ + "\u0191\u0194\u0001\u0000\u0000\u0000\u0192\u0190\u0001\u0000\u0000\u0000"+ + "\u0192\u0193\u0001\u0000\u0000\u0000\u01937\u0001\u0000\u0000\u0000\u0194"+ + "\u0192\u0001\u0000\u0000\u0000\u0195\u0196\u0005\r\u0000\u0000\u0196\u019b"+ + "\u0003:\u001d\u0000\u0197\u0198\u0005\"\u0000\u0000\u0198\u019a\u0003"+ + ":\u001d\u0000\u0199\u0197\u0001\u0000\u0000\u0000\u019a\u019d\u0001\u0000"+ + "\u0000\u0000\u019b\u0199\u0001\u0000\u0000\u0000\u019b\u019c\u0001\u0000"+ + "\u0000\u0000\u019c9\u0001\u0000\u0000\u0000\u019d\u019b\u0001\u0000\u0000"+ + "\u0000\u019e\u019f\u0003&\u0013\u0000\u019f\u01a0\u0005H\u0000\u0000\u01a0"+ + "\u01a1\u0003&\u0013\u0000\u01a1;\u0001\u0000\u0000\u0000\u01a2\u01a3\u0005"+ + "\u0001\u0000\u0000\u01a3\u01a4\u0003\u0012\t\u0000\u01a4\u01a6\u0003N"+ + "\'\u0000\u01a5\u01a7\u0003B!\u0000\u01a6\u01a5\u0001\u0000\u0000\u0000"+ + "\u01a6\u01a7\u0001\u0000\u0000\u0000\u01a7=\u0001\u0000\u0000\u0000\u01a8"+ + "\u01a9\u0005\u0007\u0000\u0000\u01a9\u01aa\u0003\u0012\t\u0000\u01aa\u01ab"+ + "\u0003N\'\u0000\u01ab?\u0001\u0000\u0000\u0000\u01ac\u01ad\u0005\u000b"+ + "\u0000\u0000\u01ad\u01ae\u0003&\u0013\u0000\u01aeA\u0001\u0000\u0000\u0000"+ + "\u01af\u01b4\u0003D\"\u0000\u01b0\u01b1\u0005\"\u0000\u0000\u01b1\u01b3"+ + "\u0003D\"\u0000\u01b2\u01b0\u0001\u0000\u0000\u0000\u01b3\u01b6\u0001"+ + "\u0000\u0000\u0000\u01b4\u01b2\u0001\u0000\u0000\u0000\u01b4\u01b5\u0001"+ + "\u0000\u0000\u0000\u01b5C\u0001\u0000\u0000\u0000\u01b6\u01b4\u0001\u0000"+ + "\u0000\u0000\u01b7\u01b8\u0003*\u0015\u0000\u01b8\u01b9\u0005!\u0000\u0000"+ + "\u01b9\u01ba\u0003,\u0016\u0000\u01baE\u0001\u0000\u0000\u0000\u01bb\u01bc"+ + "\u0007\u0006\u0000\u0000\u01bcG\u0001\u0000\u0000\u0000\u01bd\u01c0\u0003"+ + "J%\u0000\u01be\u01c0\u0003L&\u0000\u01bf\u01bd\u0001\u0000\u0000\u0000"+ + "\u01bf\u01be\u0001\u0000\u0000\u0000\u01c0I\u0001\u0000\u0000\u0000\u01c1"+ + "\u01c3\u0007\u0000\u0000\u0000\u01c2\u01c1\u0001\u0000\u0000\u0000\u01c2"+ + "\u01c3\u0001\u0000\u0000\u0000\u01c3\u01c4\u0001\u0000\u0000\u0000\u01c4"+ + "\u01c5\u0005\u001d\u0000\u0000\u01c5K\u0001\u0000\u0000\u0000\u01c6\u01c8"+ + "\u0007\u0000\u0000\u0000\u01c7\u01c6\u0001\u0000\u0000\u0000\u01c7\u01c8"+ + "\u0001\u0000\u0000\u0000\u01c8\u01c9\u0001\u0000\u0000\u0000\u01c9\u01ca"+ + "\u0005\u001c\u0000\u0000\u01caM\u0001\u0000\u0000\u0000\u01cb\u01cc\u0005"+ + "\u001b\u0000\u0000\u01ccO\u0001\u0000\u0000\u0000\u01cd\u01ce\u0007\u0007"+ + "\u0000\u0000\u01ceQ\u0001\u0000\u0000\u0000\u01cf\u01d0\u0005\u0005\u0000"+ + "\u0000\u01d0\u01d1\u0003T*\u0000\u01d1S\u0001\u0000\u0000\u0000\u01d2"+ + "\u01d3\u0005A\u0000\u0000\u01d3\u01d4\u0003\u0002\u0001\u0000\u01d4\u01d5"+ + "\u0005B\u0000\u0000\u01d5U\u0001\u0000\u0000\u0000\u01d6\u01d7\u0005\u000f"+ + "\u0000\u0000\u01d7\u01db\u00054\u0000\u0000\u01d8\u01d9\u0005\u000f\u0000"+ + "\u0000\u01d9\u01db\u00055\u0000\u0000\u01da\u01d6\u0001\u0000\u0000\u0000"+ + "\u01da\u01d8\u0001\u0000\u0000\u0000\u01dbW\u0001\u0000\u0000\u0000\u01dc"+ + "\u01dd\u0005\u0003\u0000\u0000\u01dd\u01e0\u0003&\u0013\u0000\u01de\u01df"+ + "\u0005J\u0000\u0000\u01df\u01e1\u0003&\u0013\u0000\u01e0\u01de\u0001\u0000"+ + "\u0000\u0000\u01e0\u01e1\u0001\u0000\u0000\u0000\u01e1\u01eb\u0001\u0000"+ + "\u0000\u0000\u01e2\u01e3\u0005K\u0000\u0000\u01e3\u01e8\u0003Z-\u0000"+ + "\u01e4\u01e5\u0005\"\u0000\u0000\u01e5\u01e7\u0003Z-\u0000\u01e6\u01e4"+ + "\u0001\u0000\u0000\u0000\u01e7\u01ea\u0001\u0000\u0000\u0000\u01e8\u01e6"+ + "\u0001\u0000\u0000\u0000\u01e8\u01e9\u0001\u0000\u0000\u0000\u01e9\u01ec"+ + "\u0001\u0000\u0000\u0000\u01ea\u01e8\u0001\u0000\u0000\u0000\u01eb\u01e2"+ + "\u0001\u0000\u0000\u0000\u01eb\u01ec\u0001\u0000\u0000\u0000\u01ecY\u0001"+ + "\u0000\u0000\u0000\u01ed\u01ee\u0003&\u0013\u0000\u01ee\u01ef\u0005!\u0000"+ + "\u0000\u01ef\u01f1\u0001\u0000\u0000\u0000\u01f0\u01ed\u0001\u0000\u0000"+ + "\u0000\u01f0\u01f1\u0001\u0000\u0000\u0000\u01f1\u01f2\u0001\u0000\u0000"+ + "\u0000\u01f2\u01f3\u0003&\u0013\u0000\u01f3[\u0001\u0000\u0000\u00003"+ + "gn}\u0089\u0092\u009a\u009e\u00a6\u00a8\u00ad\u00b4\u00b9\u00c0\u00c6"+ + "\u00ce\u00d0\u00e0\u00e3\u00e7\u00f1\u00f9\u0101\u0105\u010e\u0118\u011c"+ + "\u0122\u0129\u0133\u0147\u0152\u015d\u0162\u016d\u0172\u0176\u017e\u0187"+ + "\u018a\u0192\u019b\u01a6\u01b4\u01bf\u01c2\u01c7\u01da\u01e0\u01e8\u01eb"+ + "\u01f0"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java index 29aa0298c1009..ceef1b4e681a7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseListener.java @@ -108,6 +108,18 @@ public class EsqlBaseParserBaseListener implements EsqlBaseParserListener { *

The default implementation does nothing.

*/ @Override public void exitBooleanDefault(EsqlBaseParser.BooleanDefaultContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIsNull(EsqlBaseParser.IsNullContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIsNull(EsqlBaseParser.IsNullContext ctx) { } /** * {@inheritDoc} * diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java index caab129e77e72..48f5b33fcfec1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserBaseVisitor.java @@ -68,6 +68,13 @@ public class EsqlBaseParserBaseVisitor extends AbstractParseTreeVisitor im * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitBooleanDefault(EsqlBaseParser.BooleanDefaultContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIsNull(EsqlBaseParser.IsNullContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java index 6e5244069e805..04f0d6da3dbe4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserListener.java @@ -95,6 +95,18 @@ public interface EsqlBaseParserListener extends ParseTreeListener { * @param ctx the parse tree */ void exitBooleanDefault(EsqlBaseParser.BooleanDefaultContext ctx); + /** + * Enter a parse tree produced by the {@code isNull} + * labeled alternative in {@link EsqlBaseParser#booleanExpression}. + * @param ctx the parse tree + */ + void enterIsNull(EsqlBaseParser.IsNullContext ctx); + /** + * Exit a parse tree produced by the {@code isNull} + * labeled alternative in {@link EsqlBaseParser#booleanExpression}. + * @param ctx the parse tree + */ + void exitIsNull(EsqlBaseParser.IsNullContext ctx); /** * Enter a parse tree produced by the {@code regexExpression} * labeled alternative in {@link EsqlBaseParser#booleanExpression}. diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java index af0b0eb2b732c..681de2590d575 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParserVisitor.java @@ -62,6 +62,13 @@ public interface EsqlBaseParserVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitBooleanDefault(EsqlBaseParser.BooleanDefaultContext ctx); + /** + * Visit a parse tree produced by the {@code isNull} + * labeled alternative in {@link EsqlBaseParser#booleanExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIsNull(EsqlBaseParser.IsNullContext ctx); /** * Visit a parse tree produced by the {@code regexExpression} * labeled alternative in {@link EsqlBaseParser#booleanExpression}. diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlParser.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlParser.java index 493710c5b4cee..0f002ab8ef70f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlParser.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlParser.java @@ -28,6 +28,8 @@ import java.util.function.BiFunction; import java.util.function.Function; +import static org.elasticsearch.xpack.ql.parser.ParserUtils.source; + public class EsqlParser { private static final Logger log = LogManager.getLogger(EsqlParser.class); @@ -61,6 +63,8 @@ private T invokeParser( CommonTokenStream tokenStream = new CommonTokenStream(tokenSource); EsqlBaseParser parser = new EsqlBaseParser(tokenStream); + parser.addParseListener(new PostProcessor()); + parser.removeErrorListeners(); parser.addErrorListener(ERROR_LISTENER); @@ -78,6 +82,20 @@ private T invokeParser( } } + private class PostProcessor extends EsqlBaseParserBaseListener { + @Override + public void exitFunctionExpression(EsqlBaseParser.FunctionExpressionContext ctx) { + // TODO remove this at some point + EsqlBaseParser.IdentifierContext identifier = ctx.identifier(); + if (identifier.getText().equalsIgnoreCase("is_null")) { + throw new ParsingException( + source(ctx), + "is_null function is not supported anymore, please use 'is null'/'is not null' predicates instead" + ); + } + } + } + private static final BaseErrorListener ERROR_LISTENER = new BaseErrorListener() { @Override public void syntaxError( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java index f8e0ee5dac439..efb27707a7c7a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ExpressionBuilder.java @@ -27,6 +27,8 @@ import org.elasticsearch.xpack.ql.expression.predicate.logical.And; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; +import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNotNull; +import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Div; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mod; @@ -338,6 +340,13 @@ public Expression visitLogicalIn(EsqlBaseParser.LogicalInContext ctx) { return ctx.NOT() == null ? e : new Not(source, e); } + @Override + public Object visitIsNull(EsqlBaseParser.IsNullContext ctx) { + Expression exp = expression(ctx.valueExpression()); + Source source = source(ctx.valueExpression(), ctx); + return ctx.NOT() != null ? new IsNotNull(source, exp) : new IsNull(source, exp); + } + @Override public Expression visitRegexBooleanExpression(EsqlBaseParser.RegexBooleanExpressionContext ctx) { int type = ctx.kind.getType(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index e69a46e5cc5d9..66a8e3b98a2cd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -1129,7 +1129,7 @@ public void testEnrichNotNullFilter() { from test | eval x = to_string(languages) | enrich languages_idx on x - | where not is_null(language_name) + | where language_name is not null | limit 10 """); var limit = as(plan, Limit.class); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java index 25658905297d5..9536a8160f150 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java @@ -548,6 +548,17 @@ public void testSuggestAvailableProcessingCommandsOnParsingError() { } } + public void testDeprecatedIsNullFunction() { + expectError( + "from test | eval x = is_null(f)", + "line 1:23: is_null function is not supported anymore, please use 'is null'/'is not null' predicates instead" + ); + expectError( + "row x = is_null(f)", + "line 1:10: is_null function is not supported anymore, please use 'is null'/'is not null' predicates instead" + ); + } + public void testMetadataFieldOnOtherSources() { expectError( "row a = 1 [metadata _index]", From 5de0a9013fca9b260d497f93d6be2c080d7de441 Mon Sep 17 00:00:00 2001 From: Nick Chow Date: Wed, 16 Aug 2023 15:14:32 -0700 Subject: [PATCH 03/21] Documentation update that fixes a query rules code example (#98540) * Change example field in rule query guide * Change fuzzy to contains to get tests to work --------- Co-authored-by: Kathleen DeRusso --- .../search-your-data/search-using-query-rules.asciidoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference/search/search-your-data/search-using-query-rules.asciidoc b/docs/reference/search/search-your-data/search-using-query-rules.asciidoc index 2eecd891f859a..8d6cea338b246 100644 --- a/docs/reference/search/search-your-data/search-using-query-rules.asciidoc +++ b/docs/reference/search/search-your-data/search-using-query-rules.asciidoc @@ -127,7 +127,7 @@ PUT /_query_rules/my-ruleset "criteria": [ { "type": "fuzzy", - "metadata": "user.query", + "metadata": "query_string", "values": [ "puggles", "pugs" ] }, { @@ -148,8 +148,8 @@ PUT /_query_rules/my-ruleset "type": "pinned", "criteria": [ { - "type": "fuzzy", - "metadata": "user.query", + "type": "contains", + "metadata": "query_string", "values": [ "beagles" ] } ], From 1cba73f7c653f6f2c9ce54726eec45aac26af870 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Wed, 16 Aug 2023 15:53:46 -0700 Subject: [PATCH 04/21] Prune unused columns from the query (#98462) Remove unused aggregations or eval fields that are not needed in the final result. For example the query: from employees | stats c = count(salary), min = min(salary) | eval x = emp_no | keep c is now optimized as: from employees | stats c = count(salary) | keep c since neither the min or nor the x fields are actually needed. --- .../esql/optimizer/LogicalPlanOptimizer.java | 99 +++++++++ .../optimizer/LogicalPlanOptimizerTests.java | 210 ++++++++++++++++-- .../optimizer/PhysicalPlanOptimizerTests.java | 37 ++- 3 files changed, 309 insertions(+), 37 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java index c33a6c3f34432..eb20b167dbc7f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java @@ -50,8 +50,10 @@ import org.elasticsearch.xpack.ql.plan.logical.OrderBy; import org.elasticsearch.xpack.ql.plan.logical.Project; import org.elasticsearch.xpack.ql.plan.logical.UnaryPlan; +import org.elasticsearch.xpack.ql.rule.Rule; import org.elasticsearch.xpack.ql.rule.RuleExecutor; import org.elasticsearch.xpack.ql.util.CollectionUtils; +import org.elasticsearch.xpack.ql.util.Holder; import java.time.ZoneId; import java.util.ArrayList; @@ -105,6 +107,7 @@ protected static List> rules() { new SimplifyComparisonsArithmetics(EsqlDataTypes::areCompatible), // prune/elimination new PruneFilters(), + new PruneColumns(), new PruneLiteralsInOrderBy(), new PushDownAndCombineLimits(), new PushDownAndCombineFilters(), @@ -603,6 +606,102 @@ protected LogicalPlan rule(OrderBy orderBy) { } } + /** + * Remove unused columns created in the plan, in fields inside eval or aggregations inside stats. + */ + static class PruneColumns extends Rule { + + @Override + public LogicalPlan apply(LogicalPlan plan) { + var used = new Holder<>(new AttributeSet()); + // don't remove Evals without any Project/Aggregate (which might not occur as the last node in the plan) + var seenProjection = new Holder<>(Boolean.FALSE); + + // start top-to-bottom + // and track used references + var pl = plan.transformDown(p -> { + // skip nodes that simply pass the input through + if (p instanceof Limit) { + return p; + } + + // remember used + var usedSet = used.get(); + boolean recheck; + // analyze the unused items against dedicated 'producer' nodes such as Eval and Aggregate + // perform a loop to retry checking if the current node is completely eliminated + do { + recheck = false; + if (p instanceof Aggregate aggregate) { + var remaining = seenProjection.get() ? removeUnused(aggregate.aggregates(), usedSet) : null; + // no aggregates, no need + if (remaining != null) { + if (remaining.isEmpty()) { + recheck = true; + p = aggregate.child(); + } else { + p = new Aggregate(aggregate.source(), aggregate.child(), aggregate.groupings(), remaining); + } + } + + seenProjection.set(Boolean.TRUE); + } else if (p instanceof Eval eval) { + var remaining = seenProjection.get() ? removeUnused(eval.fields(), usedSet) : null; + // no fields, no eval + if (remaining != null) { + if (remaining.isEmpty()) { + p = eval.child(); + recheck = true; + } else { + p = new Eval(eval.source(), eval.child(), remaining); + } + } + } else if (p instanceof Project) { + seenProjection.set(Boolean.TRUE); + } + } while (recheck); + + var inUse = usedSet.combine(references(p)); + used.set(inUse); + + // preserve the state before going to the next node + return p; + }); + + return pl; + } + + /** + * Prunes attributes from the list not found in the given set. + * Returns null if no changed occurred. + */ + private static List removeUnused(List named, AttributeSet used) { + var clone = new ArrayList<>(named); + var it = clone.listIterator(clone.size()); + + // due to Eval, go in reverse + while (it.hasPrevious()) { + N prev = it.previous(); + if (used.contains(prev.toAttribute()) == false) { + it.remove(); + } else { + used = used.combine(prev.references()); + } + } + return clone.size() != named.size() ? clone : null; + } + + private static List expressions(LogicalPlan plan) { + List exp = new ArrayList<>(); + plan.forEachExpression(exp::add); + return exp; + } + + private static AttributeSet references(LogicalPlan plan) { + return Expressions.references(expressions(plan)); + } + } + static class PruneOrderByBeforeStats extends OptimizerRules.OptimizerRule { @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index 66a8e3b98a2cd..926967231f186 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -739,7 +739,7 @@ public void testCombineOrderBy() { | sort salary"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); + assertThat(orderNames(topN), contains("salary", "emp_no")); as(topN.child(), EsRelation.class); } @@ -751,7 +751,7 @@ public void testCombineOrderByThroughEval() { | sort x"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("x", "emp_no")); + assertThat(orderNames(topN), contains("x", "emp_no")); var eval = as(topN.child(), Eval.class); as(eval.child(), EsRelation.class); } @@ -761,12 +761,15 @@ public void testCombineOrderByThroughEvalWithTwoDefs() { from test | sort emp_no | eval x = salary + 1, y = salary + 2 - | sort x"""); + | eval z = x * y + | sort z"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("x", "emp_no")); + assertThat(orderNames(topN), contains("z", "emp_no")); var eval = as(topN.child(), Eval.class); - assertThat(eval.fields().stream().map(NamedExpression::name).toList(), contains("x", "y")); + assertThat(Expressions.names(eval.fields()), contains("z")); + eval = as(eval.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), contains("x", "y")); as(eval.child(), EsRelation.class); } @@ -778,7 +781,7 @@ public void testCombineOrderByThroughDissect() { | sort x"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("x", "emp_no")); + assertThat(orderNames(topN), contains("x", "emp_no")); var dissect = as(topN.child(), Dissect.class); as(dissect.child(), EsRelation.class); } @@ -791,7 +794,7 @@ public void testCombineOrderByThroughGrok() { | sort x"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("x", "emp_no")); + assertThat(orderNames(topN), contains("x", "emp_no")); var grok = as(topN.child(), Grok.class); as(grok.child(), EsRelation.class); } @@ -805,7 +808,7 @@ public void testCombineOrderByThroughProject() { var keep = as(plan, Project.class); var topN = as(keep.child(), TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); + assertThat(orderNames(topN), contains("salary", "emp_no")); as(topN.child(), EsRelation.class); } @@ -820,8 +823,10 @@ public void testCombineOrderByThroughProjectAndEval() { var keep = as(plan, Project.class); var topN = as(keep.child(), TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); - as(topN.child(), Eval.class); + assertThat(orderNames(topN), contains("salary", "emp_no")); + var eval = as(topN.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), contains("e")); + as(eval.child(), EsRelation.class); } public void testCombineOrderByThroughProjectWithAlias() { @@ -834,7 +839,7 @@ public void testCombineOrderByThroughProjectWithAlias() { var keep = as(plan, Project.class); var topN = as(keep.child(), TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); + assertThat(orderNames(topN), contains("salary", "emp_no")); as(topN.child(), EsRelation.class); } @@ -846,11 +851,15 @@ public void testCombineOrderByThroughFilter() { | sort salary"""); var topN = as(plan, TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); + assertThat(orderNames(topN), contains("salary", "emp_no")); var filter = as(topN.child(), Filter.class); as(filter.child(), EsRelation.class); } + private static List orderNames(TopN topN) { + return topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(); + } + public void testCombineLimitWithOrderByThroughFilterAndEval() { LogicalPlan plan = optimizedPlan(""" from test @@ -887,10 +896,10 @@ public void testCombineMultipleOrderByAndLimits() { var keep = as(plan, Project.class); var topN = as(keep.child(), TopN.class); - assertThat(topN.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("emp_no", "first_name")); + assertThat(orderNames(topN), contains("emp_no", "first_name")); var filter = as(topN.child(), Filter.class); var topN2 = as(filter.child(), TopN.class); - assertThat(topN2.order().stream().map(o -> as(o.child(), NamedExpression.class).name()).toList(), contains("salary", "emp_no")); + assertThat(orderNames(topN2), contains("salary", "emp_no")); as(topN2.child(), EsRelation.class); } @@ -1269,6 +1278,179 @@ public void testSplittingInWithFoldableValue() { assertThat(new LogicalPlanOptimizer.SplitInWithFoldableValue().rule(in), equalTo(expected)); } + public void testPruneUnusedEval() { + var plan = plan(""" + from test + | eval garbage = salary + 3 + | keep salary + """); + + var keep = as(plan, Project.class); + var limit = as(keep.child(), Limit.class); + var source = as(limit.child(), EsRelation.class); + } + + public void testPruneChainedEval() { + var plan = plan(""" + from test + | eval garbage_a = salary + 3 + | eval garbage_b = emp_no / garbage_a, garbage_c = garbage_a + | eval garbage_x = 1 - garbage_b/garbage_c + | keep salary + """); + var keep = as(plan, Project.class); + var limit = as(keep.child(), Limit.class); + var source = as(limit.child(), EsRelation.class); + } + + public void testPruneEvalDueToStats() { + var plan = plan(""" + from test + | eval garbage_a = salary + 3, x = salary + | eval garbage_b = x + 3 + | stats c = count(x) + """); + + var limit = as(plan, Limit.class); + var aggregate = as(limit.child(), Aggregate.class); + assertThat(aggregate.aggregates(), hasSize(1)); + var alias = as(aggregate.aggregates().get(0), Alias.class); + var count = as(alias.child(), Count.class); + var eval = as(aggregate.child(), Eval.class); + assertThat(eval.fields(), hasSize(1)); + var field = as(eval.fields().get(0), Alias.class); + assertThat(field.name(), is("x")); + var source = as(eval.child(), EsRelation.class); + } + + public void testPruneUnusedAggSimple() { + var plan = plan(""" + from test + | stats c = count(salary), max = max(salary), min = min(salary) + | keep c + """); + + var limit = as(plan, Limit.class); + var agg = as(limit.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(0)); + assertThat(agg.aggregates(), hasSize(1)); + var aggOne = as(agg.aggregates().get(0), Alias.class); + assertThat(aggOne.name(), is("c")); + var count = as(aggOne.child(), Count.class); + var source = as(agg.child(), EsRelation.class); + } + + public void testPruneUnusedAggMixedWithEval() { + var plan = plan(""" + from test + | stats c = count(salary), max = max(salary), min = min(salary) + | eval x = c + | keep x + """); + + var project = as(plan, Project.class); + var eval = as(project.child(), Eval.class); + var limit = as(eval.child(), Limit.class); + var agg = as(limit.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(0)); + assertThat(agg.aggregates(), hasSize(1)); + var aggOne = as(agg.aggregates().get(0), Alias.class); + assertThat(aggOne.name(), is("c")); + var count = as(aggOne.child(), Count.class); + var source = as(agg.child(), EsRelation.class); + } + + public void testPruneUnusedAggsChainedAgg() { + var plan = plan(""" + from test + | stats c = count(salary), max = max(salary), min = min(salary) + | eval x = max + min + c + | eval y = min + | eval z = c + | keep c + """); + + var project = as(plan, Project.class); + var limit = as(project.child(), Limit.class); + var agg = as(limit.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(0)); + var aggs = agg.aggregates(); + assertThat(aggs, hasSize(1)); + assertThat(Expressions.names(aggs), contains("c")); + var source = as(agg.child(), EsRelation.class); + } + + public void testPruneMixedAggInsideUnusedEval() { + var plan = plan(""" + from test + | stats c = count(salary), max = max(salary), min = min(salary) + | eval x = max + min + c + | eval y = min + | where y > 10 + | eval z = c + | keep c + """); + + var project = as(plan, Project.class); + var limit = as(project.child(), Limit.class); + var filter = as(limit.child(), Filter.class); + var eval = as(filter.child(), Eval.class); + var agg = as(eval.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(0)); + var aggs = agg.aggregates(); + assertThat(aggs, hasSize(2)); + assertThat(Expressions.names(aggs), contains("c", "min")); + var source = as(agg.child(), EsRelation.class); + } + + public void testNoPruningWhenDealingJustWithEvals() { + var plan = plan(""" + from test + | stats c = count(salary), max = max(salary), min = min(salary) + | eval x = max + min + c + | eval y = min + | eval z = c + """); + + var eval = as(plan, Eval.class); + eval = as(eval.child(), Eval.class); + eval = as(eval.child(), Eval.class); + var limit = as(eval.child(), Limit.class); + var agg = as(limit.child(), Aggregate.class); + } + + public void testNoPruningWhenChainedEvals() { + var plan = plan(""" + from test + | eval x = emp_no, y = x + 1, z = y + | keep z + """); + + var project = as(plan, Project.class); + var eval = as(project.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), contains("x", "y", "z")); + var limit = as(eval.child(), Limit.class); + var source = as(limit.child(), EsRelation.class); + } + + public void testPruningDuplicateEvals() { + var plan = plan(""" + from test + | eval x = emp_no, x = salary + | eval y = salary + | eval y = emp_no + | keep x, y + """); + + var project = as(plan, Project.class); + var eval = as(project.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), contains("y")); + eval = as(eval.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), contains("x")); + var limit = as(eval.child(), Limit.class); + var source = as(limit.child(), EsRelation.class); + } + private LogicalPlan optimizedPlan(String query) { return plan(query); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java index 709c62c0b0fb4..2eab81f02911d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java @@ -283,18 +283,13 @@ public void testTripleExtractorPerField() { var extract = as(aggregate.child(), FieldExtractExec.class); assertThat(names(extract.attributesToExtract()), contains("salary")); - var eval = as(extract.child(), EvalExec.class); - - extract = as(eval.child(), FieldExtractExec.class); - assertThat(names(extract.attributesToExtract()), contains("first_name")); - var filter = as(extract.child(), FilterExec.class); extract = as(filter.child(), FieldExtractExec.class); assertThat(names(extract.attributesToExtract()), contains("emp_no")); var query = source(extract.child()); - // for doc ids, emp_no, salary, c, and first_name - int estimatedSize = Integer.BYTES * 3 + KEYWORD_EST * 2; + // for doc ids, emp_no, salary + int estimatedSize = Integer.BYTES * 3; assertThat(query.estimatedRowSize(), equalTo(estimatedSize)); } @@ -303,13 +298,12 @@ public void testTripleExtractorPerField() { * LimitExec[10000[INTEGER]] * \_AggregateExec[[],[AVG(salary{f}#14) AS x],FINAL] * \_AggregateExec[[],[AVG(salary{f}#14) AS x],PARTIAL] - * \_EvalExec[[first_name{f}#10 AS c]] - * \_FilterExec[ROUND(emp_no{f}#9) > 10[INTEGER]] - * \_TopNExec[[Order[last_name{f}#13,ASC,LAST]],10[INTEGER]] - * \_ExchangeExec[] - * \_ProjectExec[[salary{f}#14, first_name{f}#10, emp_no{f}#9, last_name{f}#13]] -- project away _doc - * \_FieldExtractExec[salary{f}#14, first_name{f}#10, emp_no{f}#9, last_n..] -- local field extraction - * \_EsQueryExec[test], query[][_doc{f}#16], limit[10], sort[[last_name]] + * \_FilterExec[ROUND(emp_no{f}#9) > 10[INTEGER]] + * \_TopNExec[[Order[last_name{f}#13,ASC,LAST]],10[INTEGER]] + * \_ExchangeExec[] + * \_ProjectExec[[salary{f}#14, first_name{f}#10, emp_no{f}#9, last_name{f}#13]] -- project away _doc + * \_FieldExtractExec[salary{f}#14, first_name{f}#10, emp_no{f}#9, last_n..] -- local field extraction + * \_EsQueryExec[test], query[][_doc{f}#16], limit[10], sort[[last_name]] */ public void testExtractorForField() { var plan = physicalPlan(""" @@ -327,14 +321,13 @@ public void testExtractorForField() { assertThat(aggregateFinal.estimatedRowSize(), equalTo(Long.BYTES)); var aggregatePartial = as(aggregateFinal.child(), AggregateExec.class); - var eval = as(aggregatePartial.child(), EvalExec.class); - var filter = as(eval.child(), FilterExec.class); + var filter = as(aggregatePartial.child(), FilterExec.class); var topN = as(filter.child(), TopNExec.class); var exchange = asRemoteExchange(topN.child()); var project = as(exchange.child(), ProjectExec.class); var extract = as(project.child(), FieldExtractExec.class); - assertThat(names(extract.attributesToExtract()), contains("salary", "first_name", "emp_no", "last_name")); + assertThat(names(extract.attributesToExtract()), contains("salary", "emp_no", "last_name")); var source = source(extract.child()); assertThat(source.limit(), is(topN.limit())); assertThat(source.sorts(), is(sorts(topN.order()))); @@ -344,8 +337,8 @@ public void testExtractorForField() { FieldSort order = source.sorts().get(0); assertThat(order.direction(), is(ASC)); assertThat(name(order.field()), is("last_name")); - // first and last name are keywords, salary, emp_no, doc id, segment, forwards and backwards doc id maps are all ints - int estimatedSize = KEYWORD_EST * 2 + Integer.BYTES * 6; + // last name is keyword, salary, emp_no, doc id, segment, forwards and backwards doc id maps are all ints + int estimatedSize = KEYWORD_EST + Integer.BYTES * 6; assertThat(source.estimatedRowSize(), equalTo(estimatedSize)); } @@ -494,13 +487,11 @@ public void testExtractGroupingFieldsIfAggdWithEval() { assertThat(aggregate.groupings(), hasSize(1)); assertThat(aggregate.estimatedRowSize(), equalTo(Long.BYTES + KEYWORD_EST)); - var eval = as(aggregate.child(), EvalExec.class); - assertThat(names(eval.fields()), equalTo(List.of("g"))); - var extract = as(eval.child(), FieldExtractExec.class); + var extract = as(aggregate.child(), FieldExtractExec.class); assertThat(names(extract.attributesToExtract()), equalTo(List.of("first_name"))); var source = source(extract.child()); - assertThat(source.estimatedRowSize(), equalTo(Integer.BYTES + KEYWORD_EST * 2)); + assertThat(source.estimatedRowSize(), equalTo(Integer.BYTES + KEYWORD_EST)); } public void testQueryWithAggregation() { From 03344d359c9469556eb197c94e86e63173f92afb Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 11:56:54 +1000 Subject: [PATCH 05/21] Add YAML tests for Authorization using API Keys (#98527) Adds 2 new YAML tests that test authorization behaviour exclusively using API Keys 1. Indexing 2. Field Level Security --- .../authz_api_keys/10_index_authz.yml | 343 ++++++++++++++++++ .../20_field_level_security.yml | 113 ++++++ 2 files changed, 456 insertions(+) create mode 100644 x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/10_index_authz.yml create mode 100644 x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/20_field_level_security.yml diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/10_index_authz.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/10_index_authz.yml new file mode 100644 index 0000000000000..c97317b1ac971 --- /dev/null +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/10_index_authz.yml @@ -0,0 +1,343 @@ +--- +setup: + - skip: + features: headers + + - do: + cluster.health: + wait_for_status: yellow + + - do: + indices.create: + index: only_read + body: + mappings: + properties: + name: + type: "keyword" + + - do: + indices.create: + index: only_create_doc + body: + mappings: + properties: + name: + type: "keyword" + + - do: + indices.create: + index: only_index + body: + mappings: + properties: + name: + type: "keyword" + + - do: + indices.create: + index: only_delete + body: + mappings: + properties: + name: + type: "keyword" + + - do: + indices.create: + index: everything + body: + mappings: + properties: + name: + type: "keyword" + +--- +"Test indexing documents with API Key": + - do: + security.create_api_key: + body: + name: "test-index-access" + expiration: "1d" + role_descriptors: + index_access: + indices: + - names: [ "only_read" ] + privileges: [ "read" ] + - names: [ "only_create_doc" ] + privileges: [ "create_doc" ] + - names: [ "only_index" ] + privileges: [ "index" ] + - names: [ "only_delete" ] + privileges: [ "delete" ] + - names: [ "everything" ] + privileges: [ "all" ] + - match: { name: "test-index-access" } + - is_true: id + - set: + id: api_key_id + encoded: credentials + + ### + # Successful indexing + ### + + # document create + - do: + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "c1" + index: only_create_doc + body: > + { + "name" : "create-doc-1" + } + + - do: + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "i1" + index: only_index + body: > + { + "name" : "index-doc-1" + } + + - do: + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "e1" + index: everything + body: > + { + "name" : "everything-doc-1" + } + + # document index + - do: + headers: + Authorization: "ApiKey ${credentials}" + index: + # no "id" due to create_doc privilege + index: only_create_doc + body: > + { + "name" : "create-doc-2" + } + + - do: + headers: + Authorization: "ApiKey ${credentials}" + index: + id: "i2" + index: only_index + body: > + { + "name" : "index-doc-2" + } + + - do: + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "e2" + index: everything + body: > + { + "name" : "everything-doc-2" + } + + # bulk + - do: + headers: + Authorization: "ApiKey ${credentials}" + bulk: + body: + - '{"create": {"_index": "only_create_doc", "_id": "c3"}}' + - '{"name": "create-doc-3"}' + - '{"index": {"_index": "only_index", "_id": "i3"}}' + - '{"name": "index-doc-3"}' + - '{"index": {"_index": "everything" }}' + - '{"name": "everything-doc-3"}' + - match: { errors: false } + + - do: + indices.refresh: + index: only_create_doc,only_index,everything + + - do: + search: + index: only_create_doc + - match: { hits.total.relation: "eq" } + - match: { hits.total.value: 3 } + + - do: + search: + index: only_index + - match: { hits.total.value: 3 } + - match: { hits.total.relation: "eq" } + + - do: + search: + index: everything + - match: { hits.total.value: 3 } + - match: { hits.total.relation: "eq" } + + ### + # Authz failures + ### + + # Error: Cannot create docs in an index with read only privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "r1" + index: only_read + body: > + { + "name" : "read-doc-1" + } + + # Error: Cannot index docs in an index with read only privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + index: + id: "r2" + index: only_read + body: > + { + "name" : "read-doc-2" + } + + # Error: Cannot create docs in an index with only delete privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + create: + id: "d1" + index: only_delete + body: > + { + "name" : "delete-doc-1" + } + + # Error: Cannot index docs in an index with only delete privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + index: + index: only_delete + body: > + { + "name" : "delete-doc-2" + } + + # Error: Cannot index docs (with an id) in an index with only create_doc privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + index: + id: "c4" + index: only_create_doc + body: > + { + "name" : "create-doc-4" + } + + # Error: Cannot update docs in an index with only create_doc privileges + - do: + catch: forbidden + headers: + Authorization: "ApiKey ${credentials}" + update: + id: "c1" + index: only_create_doc + body: > + { + "doc": { "name" : "updated-create-doc-1" } + } + + # Subset of the above, via bulk + - do: + headers: + Authorization: "ApiKey ${credentials}" + bulk: + body: + - '{"index": {"_index": "only_read", "_id": "r3"}}' + - '{"name": "read-doc-3"}' + - '{"create": {"_index": "only_delete"}}' + - '{"name": "delete-doc-3"}' + - '{"update": {"_index": "only_create_doc", "_id": "c2"}}' + - '{"doc": {"name": "updated-create-doc-2"}}' + - match: { errors: true } + - match: { items.0.index.status: 403 } + - match: { items.0.index.error.type: "security_exception" } + - match: { items.1.create.status: 403 } + - match: { items.1.create.error.type: "security_exception" } + - match: { items.2.update.status: 403 } + - match: { items.2.update.error.type: "security_exception" } + + - do: + indices.refresh: + index: only_create_doc,only_read,only_delete + + - do: + search: + index: only_create_doc,only_read,only_delete + - match: { hits.total.relation: "eq" } + - match: { hits.total.value: 3 } # Existing docs + + ### + # Mixed success / failure + ### + + - do: + headers: + Authorization: "ApiKey ${credentials}" + bulk: + body: + - '{"index": {"_index": "only_read", "_id": "r4"}}' + - '{"name": "read-doc-4"}' + - '{"index": {"_index": "only_index", "_id": "i4"}}' + - '{"name": "index-doc-4"}' + - '{"create": {"_index": "only_create_doc" }}' + - '{"name": "create-doc-5"}' + - match: { errors: true } + - match: { items.0.index.status: 403 } + - match: { items.0.index.error.type: "security_exception" } + - match: { items.1.index.status: 201 } + - match: { items.1.index._id: "i4" } + - match: { items.2.create.status: 201 } + - is_true: items.2.create._id + + - do: + indices.refresh: + index: only_create_doc,only_read,only_index + + - do: + search: + index: only_create_doc + - match: { hits.total.relation: "eq" } + - match: { hits.total.value: 4 } # 3 existing + 1 new + + - do: + search: + index: only_read + - match: { hits.total.relation: "eq" } + - match: { hits.total.value: 0 } + + - do: + search: + index: only_index + - match: { hits.total.relation: "eq" } + - match: { hits.total.value: 4 } # 3 existing + 1 new diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/20_field_level_security.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/20_field_level_security.yml new file mode 100644 index 0000000000000..f9872423c3bf1 --- /dev/null +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/security/authz_api_keys/20_field_level_security.yml @@ -0,0 +1,113 @@ +--- +setup: + - skip: + features: headers + + - do: + cluster.health: + wait_for_status: yellow + + - do: + indices.create: + index: index_fls1 + body: + mappings: + properties: + name: + type: "keyword" + secret: + type: "keyword" + + - do: + indices.create: + index: index_fls2 + body: + mappings: + properties: + name: + type: "keyword" + object: + type: "object" + properties: + secret: + type: keyword + public: + type: keyword +--- +"Retrieve documents with FLS": + + - do: + bulk: + refresh: true + body: + - '{"index": {"_index": "index_fls1", "_id": "1a" }}' + - '{"name": "i1_doc", "secret":"squirrel"}' + - '{"index": {"_index": "index_fls2", "_id": "2a"}}' + - '{"name": "i2_doc", "object":{ "secret":"mission", "public":"interest" }}' + - match: { errors: false } + + - do: + security.create_api_key: + body: + name: "test-fls" + expiration: "1d" + role_descriptors: + index_access: + indices: + - names: [ "index_fls1" ] + privileges: [ "read" ] + field_security: + grant: [ "name" ] + - names: [ "index_fls2" ] + privileges: [ "read", "monitor" ] + field_security: + grant: [ "*" ] + except: [ "object.secret" ] + - match: { name: "test-fls" } + - is_true: id + - set: + id: api_key_id + encoded: credentials + + # With superuser... + - do: + search: + index: index_fls1 + - match: { hits.total.value: 1 } + - match: { hits.total.relation: "eq" } + - match: { hits.hits.0._source.name: "i1_doc" } + - is_true: "hits.hits.0._source.secret" + - match: { hits.hits.0._source.secret: "squirrel" } + + # With FLS API Key + - do: + headers: + Authorization: "ApiKey ${credentials}" + search: + index: index_fls1 + - match: { hits.total.value: 1 } + - match: { hits.total.relation: "eq" } + - match: { hits.hits.0._source.name: "i1_doc" } + - is_false: "hits.hits.0._source.secret" + + + # With superuser... + - do: + get: + index: index_fls2 + id: 2a + - match: { _source.name: "i2_doc" } + - match: { _source.object.secret: "mission" } + - match: { _source.object.public: "interest" } + - is_true: "_source.object.secret" + + # With FLS API Key + - do: + headers: + Authorization: "ApiKey ${credentials}" + get: + index: index_fls2 + id: 2a + - match: { _source.name: "i2_doc" } + - match: { _source.object.public: "interest" } + - is_false: "_source.object.secret" From 00fe655ddc326f2fbb87d42890e4a15bbcbd42d0 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 13:09:02 +1000 Subject: [PATCH 06/21] Mute JobNodeSelectorTests (#98554) Relates: #98552 --- .../org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java index be419e2d2497f..32a684097d601 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java @@ -6,6 +6,7 @@ */ package org.elasticsearch.xpack.ml.job; +import org.apache.lucene.tests.util.LuceneTestCase; import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; @@ -58,6 +59,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98552") public class JobNodeSelectorTests extends ESTestCase { // To simplify the logic in this class all jobs have the same memory requirement From 874fbbc2f05b201873edc21b5baa36753935296f Mon Sep 17 00:00:00 2001 From: William Brafford Date: Thu, 17 Aug 2023 00:03:12 -0400 Subject: [PATCH 07/21] Add mappings version number to SystemIndexDescriptor (#97934) This PR adds a mappings version number to system index descriptor, which is intended to replace the use of Version to signal changes in the mappings for the descriptor. This value is required for managed system indices. Previously, most of the system index descriptors automatically incremented their mapping version with each release, which meant that the mappings would stay up-to-date with any additive changes. Now, developers will need to increment the mapping version whenever there's a change. * Add MappingsVersion inner class to SystemIndexDescriptor * Add mappings version to metadata in all system index mappings * Rename version meta key ('system' -> 'managed') * Update mappings for ML indices if required * Trigger ML index mappings updates based on new index mappings version. --------- Co-authored-by: Ed Savage --- .../ingest/geoip/IngestGeoIpPlugin.java | 2 + .../AbstractFeatureMigrationIntegTest.java | 1 + .../elasticsearch/http/SystemIndexRestIT.java | 1 + .../system/indices/SystemIndicesQA.java | 1 + .../indices/create/CreateSystemIndicesIT.java | 11 +-- .../aliases/NetNewSystemIndexAliasIT.java | 1 + .../SystemIndexMappingUpdateServiceIT.java | 11 +-- .../indices/TestSystemIndexDescriptor.java | 2 + .../indices/SystemIndexDescriptor.java | 92 ++++++++++++++++--- .../SystemIndexMappingUpdateService.java | 7 +- .../SynonymsManagementAPIService.java | 2 + .../tasks/TaskResultsService.java | 2 + .../get/TransportGetAliasesActionTests.java | 2 +- .../TransportCreateIndexActionTests.java | 10 +- .../indices/resolve/ResolveIndexTests.java | 12 ++- ...ystemIndexMetadataUpgradeServiceTests.java | 12 ++- .../indices/SystemIndexDescriptorTests.java | 91 +++++++++++++++++- .../SystemIndexMappingUpdateServiceTests.java | 5 +- .../core/async/AsyncTaskIndexService.java | 2 + .../xpack/core/ml/MlConfigIndex.java | 10 +- .../xpack/core/ml/MlMetaIndex.java | 10 +- .../xpack/core/ml/MlStatsIndex.java | 9 +- .../core/ml/annotations/AnnotationIndex.java | 12 ++- .../persistence/InferenceIndexConstants.java | 10 +- .../persistence/AnomalyDetectorsIndex.java | 5 +- .../persistence/ElasticsearchMappings.java | 27 +++--- .../ml/notifications/NotificationsIndex.java | 6 +- .../ElasticsearchMappingsTests.java | 91 ++++++++++++++---- .../security/test/TestRestrictedIndices.java | 1 + .../main/resources/fleet-actions-results.json | 3 +- .../src/main/resources/fleet-actions.json | 3 +- .../src/main/resources/fleet-agents.json | 3 +- .../src/main/resources/fleet-artifacts.json | 3 +- .../resources/fleet-enrollment-api-keys.json | 3 +- .../main/resources/fleet-policies-leader.json | 3 +- .../src/main/resources/fleet-policies.json | 3 +- .../src/main/resources/fleet-secrets.json | 3 +- .../src/main/resources/fleet-servers.json | 3 +- .../ml/annotations_index_mappings.json | 3 +- .../results_index_mappings.json | 3 +- .../resources/ml/config_index_mappings.json | 3 +- .../ml/inference_index_mappings.json | 3 +- .../resources/ml/meta_index_mappings.json | 3 +- .../ml/notifications_index_mappings.json | 3 +- .../resources/ml/stats_index_mappings.json | 3 +- .../rules/QueryRulesIndexService.java | 2 + .../search/SearchApplicationIndexService.java | 2 + .../org/elasticsearch/xpack/fleet/Fleet.java | 39 +++++--- .../xpack/logstash/Logstash.java | 2 + .../ml/action/TransportOpenJobAction.java | 3 +- .../TransportPutDataFrameAnalyticsAction.java | 3 +- .../TransportRevertModelSnapshotAction.java | 3 +- ...ansportUpdateDataFrameAnalyticsAction.java | 3 +- ...ransportUpgradeJobModelSnapshotAction.java | 3 +- .../xpack/ml/datafeed/DatafeedManager.java | 6 +- .../dataframe/DataFrameAnalyticsManager.java | 3 +- .../inference/TrainedModelStatsService.java | 3 +- .../xpack/ml/job/JobManager.java | 6 +- .../autodetect/AutodetectProcessManager.java | 6 +- .../upgrader/SnapshotUpgradeTaskExecutor.java | 6 +- .../task/OpenJobPersistentTasksExecutor.java | 3 +- .../SearchableSnapshots.java | 2 + .../support/SecurityIndexManager.java | 2 +- .../support/SecuritySystemIndices.java | 6 ++ .../persistence/TransformInternalIndex.java | 6 +- .../elasticsearch/xpack/watcher/Watcher.java | 4 + .../upgrades/MlMappingsUpgradeIT.java | 15 +++ 67 files changed, 497 insertions(+), 127 deletions(-) diff --git a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/IngestGeoIpPlugin.java b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/IngestGeoIpPlugin.java index 988f1f1a4032c..03607b908d375 100644 --- a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/IngestGeoIpPlugin.java +++ b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/IngestGeoIpPlugin.java @@ -72,6 +72,7 @@ public class IngestGeoIpPlugin extends Plugin implements IngestPlugin, SystemIndexPlugin, Closeable, PersistentTaskPlugin, ActionPlugin { public static final Setting CACHE_SIZE = Setting.longSetting("ingest.geoip.cache_size", 1000, 0, Setting.Property.NodeScope); + private static final int GEOIP_INDEX_MAPPINGS_VERSION = 1; private final SetOnce ingestService = new SetOnce<>(); private final SetOnce databaseRegistry = new SetOnce<>(); @@ -222,6 +223,7 @@ private static XContentBuilder mappings() { .startObject(SINGLE_MAPPING_NAME) .startObject("_meta") .field("version", Version.CURRENT) + .field(SystemIndexDescriptor.VERSION_META_KEY, GEOIP_INDEX_MAPPINGS_VERSION) .endObject() .field("dynamic", "strict") .startObject("properties") diff --git a/modules/reindex/src/internalClusterTest/java/org/elasticsearch/migration/AbstractFeatureMigrationIntegTest.java b/modules/reindex/src/internalClusterTest/java/org/elasticsearch/migration/AbstractFeatureMigrationIntegTest.java index 212a96ff54ff3..a8e8e7bc935ee 100644 --- a/modules/reindex/src/internalClusterTest/java/org/elasticsearch/migration/AbstractFeatureMigrationIntegTest.java +++ b/modules/reindex/src/internalClusterTest/java/org/elasticsearch/migration/AbstractFeatureMigrationIntegTest.java @@ -209,6 +209,7 @@ static String createMapping(boolean descriptorManaged, boolean descriptorInterna { builder.startObject("_meta"); builder.field(VERSION_META_KEY, META_VERSION); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1); builder.field(DESCRIPTOR_MANAGED_META_KEY, descriptorManaged); builder.field(DESCRIPTOR_INTERNAL_META_KEY, descriptorInternal); builder.endObject(); diff --git a/qa/smoke-test-http/src/javaRestTest/java/org/elasticsearch/http/SystemIndexRestIT.java b/qa/smoke-test-http/src/javaRestTest/java/org/elasticsearch/http/SystemIndexRestIT.java index 9847534c1c042..7d0095dd81f63 100644 --- a/qa/smoke-test-http/src/javaRestTest/java/org/elasticsearch/http/SystemIndexRestIT.java +++ b/qa/smoke-test-http/src/javaRestTest/java/org/elasticsearch/http/SystemIndexRestIT.java @@ -169,6 +169,7 @@ public Collection getSystemIndexDescriptors(Settings sett { builder.startObject("_meta"); builder.field("version", Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/qa/system-indices/src/main/java/org/elasticsearch/system/indices/SystemIndicesQA.java b/qa/system-indices/src/main/java/org/elasticsearch/system/indices/SystemIndicesQA.java index f55b350520106..d4b242e613c95 100644 --- a/qa/system-indices/src/main/java/org/elasticsearch/system/indices/SystemIndicesQA.java +++ b/qa/system-indices/src/main/java/org/elasticsearch/system/indices/SystemIndicesQA.java @@ -111,6 +111,7 @@ private static XContentBuilder mappings() { .startObject(SINGLE_MAPPING_NAME) .startObject("_meta") .field("version", Version.CURRENT) + .field(SystemIndexDescriptor.VERSION_META_KEY, 1) .endObject() .field("dynamic", "strict") .startObject("properties") diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java index f36c2aae7f8ad..f5a2121b2dde9 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java @@ -29,6 +29,7 @@ import org.elasticsearch.cluster.metadata.Template; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; +import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.indices.TestSystemIndexDescriptor; import org.elasticsearch.indices.TestSystemIndexDescriptorAllowsTemplates; import org.elasticsearch.indices.TestSystemIndexPlugin; @@ -38,8 +39,6 @@ import org.junit.After; import org.junit.Before; -import java.io.IOException; -import java.io.UncheckedIOException; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -51,7 +50,6 @@ import static org.elasticsearch.indices.TestSystemIndexDescriptor.INDEX_NAME; import static org.elasticsearch.indices.TestSystemIndexDescriptor.PRIMARY_INDEX_NAME; -import static org.elasticsearch.test.XContentTestUtils.convertToXContent; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -352,7 +350,6 @@ private void assertHasAliases(Set aliasNames, String name, String primar /** * Fetch the mappings and settings for {@link TestSystemIndexDescriptor#INDEX_NAME} and verify that they match the expected values. - * Note that in the case of the mappings, this is just a dumb string comparison, so order of keys matters. */ private void assertMappingsAndSettings(String expectedMappings, String concreteIndex) { final GetMappingsResponse getMappingsResponse = indicesAdmin().getMappings(new GetMappingsRequest().indices(INDEX_NAME)) @@ -366,11 +363,7 @@ private void assertMappingsAndSettings(String expectedMappings, String concreteI ); final Map sourceAsMap = mappings.get(concreteIndex).getSourceAsMap(); - try { - assertThat(convertToXContent(sourceAsMap, XContentType.JSON).utf8ToString(), equalTo(expectedMappings)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, false))); final GetSettingsResponse getSettingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(INDEX_NAME)) .actionGet(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/aliases/NetNewSystemIndexAliasIT.java b/server/src/internalClusterTest/java/org/elasticsearch/aliases/NetNewSystemIndexAliasIT.java index 9f2a9d3a48162..105e9f5ec91f0 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/aliases/NetNewSystemIndexAliasIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/aliases/NetNewSystemIndexAliasIT.java @@ -68,6 +68,7 @@ public Collection getSystemIndexDescriptors(Settings sett { builder.startObject("_meta"); builder.field("version", Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceIT.java index 279f56f33c1a7..486aa8d1f5084 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceIT.java @@ -17,13 +17,12 @@ import org.elasticsearch.cluster.metadata.MappingMetadata; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; +import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.xcontent.XContentType; import org.junit.Before; -import java.io.IOException; -import java.io.UncheckedIOException; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -31,7 +30,6 @@ import static org.elasticsearch.indices.TestSystemIndexDescriptor.INDEX_NAME; import static org.elasticsearch.indices.TestSystemIndexDescriptor.PRIMARY_INDEX_NAME; -import static org.elasticsearch.test.XContentTestUtils.convertToXContent; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; @@ -122,7 +120,6 @@ private void triggerClusterStateUpdates() { /** * Fetch the mappings and settings for {@link TestSystemIndexDescriptor#INDEX_NAME} and verify that they match the expected values. - * Note that in the case of the mappings, this is just a dumb string comparison, so order of keys matters. */ private void assertMappingsAndSettings(String expectedMappings) { final GetMappingsResponse getMappingsResponse = indicesAdmin().getMappings(new GetMappingsRequest().indices(INDEX_NAME)) @@ -136,11 +133,7 @@ private void assertMappingsAndSettings(String expectedMappings) { ); final Map sourceAsMap = mappings.get(PRIMARY_INDEX_NAME).getSourceAsMap(); - try { - assertThat(convertToXContent(sourceAsMap, XContentType.JSON).utf8ToString(), equalTo(expectedMappings)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, false))); final GetSettingsResponse getSettingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(INDEX_NAME)) .actionGet(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java index 58830f978ee30..0a090fa889a29 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java @@ -97,6 +97,7 @@ public static String getOldMappings() { builder.startObject(); { builder.startObject("_meta"); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, 0); builder.field("version", Version.CURRENT.previousMajor().toString()); builder.endObject(); @@ -123,6 +124,7 @@ public static String getNewMappings() { builder.startObject(); { builder.startObject("_meta"); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1); builder.field("version", Version.CURRENT.toString()); builder.endObject(); diff --git a/server/src/main/java/org/elasticsearch/indices/SystemIndexDescriptor.java b/server/src/main/java/org/elasticsearch/indices/SystemIndexDescriptor.java index fdccfa72d785f..4d37cea8bcf98 100644 --- a/server/src/main/java/org/elasticsearch/indices/SystemIndexDescriptor.java +++ b/server/src/main/java/org/elasticsearch/indices/SystemIndexDescriptor.java @@ -12,6 +12,8 @@ import org.apache.lucene.util.automaton.CharacterRunAutomaton; import org.apache.lucene.util.automaton.Operations; import org.elasticsearch.Version; +import org.elasticsearch.action.admin.indices.create.AutoCreateAction; +import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.metadata.SystemIndexMetadataUpgradeService; @@ -130,9 +132,13 @@ public class SystemIndexDescriptor implements IndexPatternMatcher, Comparable_meta in the index mappings - * that contains the index's mappings' version. + * that contains the index's mappings' {@link Version}. We need to read and write this field for + * backwards compatibility. */ - private final String versionMetaKey; + private final String mappingsNodeVersionMetaKey; + + /** The version meta key for the integer system index mapping version */ + public static final String VERSION_META_KEY = "managed_index_mappings_version"; /** For internally-managed indices, specifies the origin to use when creating or updating the index */ private final String origin; @@ -140,8 +146,11 @@ public class SystemIndexDescriptor implements IndexPatternMatcher, Comparable_meta where a version can be found, which indicates the + * @param mappingsNodeVersionMetaKey a mapping key under _meta where a version can be found, which indicates the * Elasticsearch version when the index was created. * @param origin the client origin to use when creating this index. Internal system indices must not provide an origin, while external * system indices must do so. @@ -209,7 +218,7 @@ protected SystemIndexDescriptor( Settings settings, String aliasName, int indexFormat, - String versionMetaKey, + String mappingsNodeVersionMetaKey, String origin, Version minimumNodeVersion, Type type, @@ -262,18 +271,22 @@ protected SystemIndexDescriptor( Objects.requireNonNull(settings, "Must supply settings for a managed system index"); Strings.requireNonEmpty(mappings, "Must supply mappings for a managed system index"); Strings.requireNonEmpty(primaryIndex, "Must supply primaryIndex for a managed system index"); - Strings.requireNonEmpty(versionMetaKey, "Must supply versionMetaKey for a managed system index"); + Strings.requireNonEmpty(mappingsNodeVersionMetaKey, "Must supply nodeVersionMetaKey for a managed system index"); Strings.requireNonEmpty(origin, "Must supply origin for a managed system index"); if (settings.getAsInt(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), 0) != indexFormat) { throw new IllegalArgumentException("Descriptor index format does not match index format in managed settings"); } - this.mappingVersion = extractVersionFromMappings(mappings, versionMetaKey); + this.mappingsNodeVersion = extractNodeVersionFromMappings(mappings, mappingsNodeVersionMetaKey); + this.mappingsVersion = extractVersionFromMappings(mappings); + assert mappingsVersion.version >= 0 : "The mappings version must not be negative"; + } else { assert Objects.isNull(settings) : "Unmanaged index descriptors should not have settings"; assert Objects.isNull(mappings) : "Unmanaged index descriptors should not have mappings"; assert Objects.isNull(primaryIndex) : "Unmanaged index descriptors should not have a primary index"; - assert Objects.isNull(versionMetaKey) : "Unmanaged index descriptors should not have a version meta key"; - this.mappingVersion = null; + assert Objects.isNull(mappingsNodeVersionMetaKey) : "Unmanaged index descriptors should not have a version meta key"; + this.mappingsNodeVersion = null; + this.mappingsVersion = null; } Objects.requireNonNull(allowedElasticProductOrigins, "allowedProductOrigins must not be null"); @@ -355,7 +368,7 @@ protected SystemIndexDescriptor( throw new IllegalArgumentException("System indices must have " + IndexMetadata.SETTING_INDEX_HIDDEN + " set to true."); } this.indexFormat = indexFormat; - this.versionMetaKey = versionMetaKey; + this.mappingsNodeVersionMetaKey = mappingsNodeVersionMetaKey; this.origin = origin; this.minimumNodeVersion = minimumNodeVersion; this.type = type; @@ -450,9 +463,9 @@ public int getIndexFormat() { return this.indexFormat; } - public String getVersionMetaKey() { + public String getMappingsNodeVersionMetaKey() { assert isAutomaticallyManaged() : "Do not request version meta keys for unmanaged system indices"; - return this.versionMetaKey; + return this.mappingsNodeVersionMetaKey; } public Version getMinimumNodeVersion() { @@ -506,11 +519,23 @@ public boolean allowsTemplates() { return allowsTemplates; } - public Version getMappingVersion() { + /** + * Use of the mappings {@link Version} should be replaced with the value returned from {@link #getMappingsVersion()} + * @return Elasticsearch version associated with this descriptor's mappings. + */ + @Deprecated + public Version getMappingsNodeVersion() { + if (isAutomaticallyManaged() == false) { + throw new IllegalStateException(this + " is not managed so there are no mappings or version"); + } + return mappingsNodeVersion; + } + + public MappingsVersion getMappingsVersion() { if (isAutomaticallyManaged() == false) { throw new IllegalStateException(this + " is not managed so there are no mappings or version"); } - return mappingVersion; + return mappingsVersion; } /** @@ -612,6 +637,20 @@ public boolean isInternal() { } } + /** + * The version of the mapping, which should be stored as an int in a mapping metadata + * field. This will be used with prior index descriptors to determine which mappings + * should be used when creating a system index, and it will be used to determine when + * mappings should be updated with the latest mappings from the system index descriptor. + * See {@link SystemIndexMappingUpdateService}, {@link TransportCreateIndexAction}, + * and {@link AutoCreateAction}. + *

+ * Version should be a non-negative integer for a managed index, or -1 for unmanaged indices. + * The hash is a hash of the system index descriptor's mappings so that we can warn + * in case of inconsistencies across nodes. + */ + public record MappingsVersion(int version, int hash) {}; + /** * Provides a fluent API for building a {@link SystemIndexDescriptor}. Validation still happens in that class. */ @@ -818,8 +857,31 @@ static boolean findDynamicMapping(Map map) { return false; } + @SuppressWarnings("unchecked") // we do a lot of casting of maps + private static MappingsVersion extractVersionFromMappings(String mappings) { + final Map mappingsMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), mappings, true); + final Map doc = (Map) mappingsMap.get("_doc"); + final Map meta; + final Map properties; + if (doc == null) { + meta = (Map) mappingsMap.get("_meta"); + properties = (Map) mappingsMap.get("properties"); + } else { + meta = (Map) doc.get("_meta"); + properties = (Map) doc.get("properties"); + } + if (meta == null) { + throw new IllegalStateException("mappings do not have _meta field"); + } + final Integer value = (Integer) meta.get(VERSION_META_KEY); + if (value == null) { + throw new IllegalArgumentException("mappings do not have a version in _meta." + VERSION_META_KEY); + } + return new MappingsVersion(value, Objects.hash(properties)); + } + @SuppressWarnings("unchecked") - private static Version extractVersionFromMappings(String mappings, String versionMetaKey) { + private static Version extractNodeVersionFromMappings(String mappings, String versionMetaKey) { final Map mappingsMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), mappings, false); final Map doc = (Map) mappingsMap.get("_doc"); final Map meta; diff --git a/server/src/main/java/org/elasticsearch/indices/SystemIndexMappingUpdateService.java b/server/src/main/java/org/elasticsearch/indices/SystemIndexMappingUpdateService.java index d5f4d32914179..d1f8acfccc0ac 100644 --- a/server/src/main/java/org/elasticsearch/indices/SystemIndexMappingUpdateService.java +++ b/server/src/main/java/org/elasticsearch/indices/SystemIndexMappingUpdateService.java @@ -289,7 +289,7 @@ private static Version readMappingVersion(SystemIndexDescriptor descriptor, Mapp return Version.V_EMPTY; } - final Object rawVersion = meta.get(descriptor.getVersionMetaKey()); + final Object rawVersion = meta.get(descriptor.getMappingsNodeVersionMetaKey()); if (rawVersion instanceof Integer) { // This can happen with old system indices, such as .tasks, which were created before we used an Elasticsearch // version here. We should just replace the template to be sure. @@ -297,7 +297,10 @@ private static Version readMappingVersion(SystemIndexDescriptor descriptor, Mapp } final String versionString = rawVersion != null ? rawVersion.toString() : null; if (versionString == null) { - logger.warn("No value found in mappings for [_meta.{}], assuming mappings update required", descriptor.getVersionMetaKey()); + logger.warn( + "No value found in mappings for [_meta.{}], assuming mappings update required", + descriptor.getMappingsNodeVersionMetaKey() + ); // If we called `Version.fromString(null)`, it would return `Version.CURRENT` and we wouldn't update the mappings return Version.V_EMPTY; } diff --git a/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java b/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java index b4f84f2fdd1db..848f103aaaf56 100644 --- a/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java +++ b/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java @@ -81,6 +81,7 @@ public class SynonymsManagementAPIService { public static final int MAX_SYNONYMS_SETS = 10_000; private static final String SYNONYM_RULE_ID_FIELD = SynonymRule.ID_FIELD.getPreferredName(); private static final String SYNONYM_SETS_AGG_NAME = "synonym_sets_aggr"; + private static final int SYNONYMS_INDEX_MAPPINGS_VERSION = 1; private final Client client; @@ -123,6 +124,7 @@ private static XContentBuilder mappings() { builder.startObject("_meta"); { builder.field("version", Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, SYNONYMS_INDEX_MAPPINGS_VERSION); } builder.endObject(); builder.field("dynamic", "strict"); diff --git a/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java b/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java index d4f4058e358cb..1e42417aa2471 100644 --- a/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java +++ b/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java @@ -66,6 +66,7 @@ public class TaskResultsService { * time is 600000 milliseconds, ten minutes. */ static final BackoffPolicy STORE_BACKOFF_POLICY = BackoffPolicy.exponentialBackoff(timeValueMillis(250), 14); + private static final int TASK_RESULTS_INDEX_MAPPINGS_VERSION = 0; private final Client client; @@ -124,6 +125,7 @@ private static XContentBuilder getTaskResultIndexMappings() { { builder.startObject("_meta"); builder.field(TASK_RESULT_MAPPING_VERSION_META_FIELD, Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, TASK_RESULTS_INDEX_MAPPINGS_VERSION); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesActionTests.java index 2919fd83a446f..6ebdb2729765e 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesActionTests.java @@ -274,7 +274,7 @@ public void testNetNewSystemIndicesDontErrorWhenNotRequested() { .setAliasName(".y") .setPrimaryIndex(".b") .setDescription(this.getTestName()) - .setMappings("{\"_meta\": {\"version\": \"1.0.0\"}}") + .setMappings("{\"_meta\": {\"version\": \"1.0.0\", \"" + SystemIndexDescriptor.VERSION_META_KEY + "\": 0}}") .setSettings(Settings.EMPTY) .setVersionMetaKey("version") .setOrigin(this.getTestName()) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexActionTests.java index 5ccb7900d7ff2..671bf13fb0e77 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexActionTests.java @@ -30,6 +30,7 @@ import org.mockito.ArgumentCaptor; import java.util.List; +import java.util.Locale; import static org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_INDEX_HIDDEN; import static org.hamcrest.Matchers.equalTo; @@ -63,7 +64,14 @@ public class TransportCreateIndexActionTests extends ESTestCase { .setPrimaryIndex(MANAGED_SYSTEM_INDEX_NAME + "-primary") .setType(SystemIndexDescriptor.Type.INTERNAL_MANAGED) .setSettings(SystemIndexDescriptor.DEFAULT_SETTINGS) - .setMappings("{\"_meta\": {\"version\": \"1.0.0\"}}") + .setMappings(String.format(Locale.ROOT, """ + { + "_meta": { + "version": "1.0.0", + "%s": 0 + } + }" + """, SystemIndexDescriptor.VERSION_META_KEY)) .setVersionMetaKey("version") .setOrigin("origin") .build() diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java index 2f82ceb679179..45a21c13f5861 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -512,7 +513,16 @@ private SystemIndices addSystemIndex(Metadata.Builder mdBuilder) { .setAllowedElasticProductOrigins(List.of("test-net-new-system")) .setNetNew() .setSettings(Settings.EMPTY) - .setMappings("{ \"_doc\": { \"_meta\": { \"version\": \"8.0.0\" } } }") + .setMappings(String.format(Locale.ROOT, """ + { + "_doc": { + "_meta": { + "version": "8.0.0", + "%s": 1 + } + } + } + """, SystemIndexDescriptor.VERSION_META_KEY)) .setPrimaryIndex(".test-net-new-system-1") .setVersionMetaKey("version") .setOrigin("system") diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/SystemIndexMetadataUpgradeServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/SystemIndexMetadataUpgradeServiceTests.java index 9b4307aae9c3e..bfdef69a5275a 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/SystemIndexMetadataUpgradeServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/SystemIndexMetadataUpgradeServiceTests.java @@ -19,6 +19,7 @@ import org.junit.Before; import java.util.List; +import java.util.Locale; import java.util.Map; import static org.hamcrest.Matchers.equalTo; @@ -26,7 +27,16 @@ public class SystemIndexMetadataUpgradeServiceTests extends ESTestCase { - private static final String MAPPINGS = "{ \"_doc\": { \"_meta\": { \"version\": \"7.4.0\" } } }"; + private static final String MAPPINGS = String.format(Locale.ROOT, """ + { + "_doc": { + "_meta": { + "version": "7.4.0", + "%s": 0 + } + } + } + """, SystemIndexDescriptor.VERSION_META_KEY); private static final String SYSTEM_INDEX_NAME = ".myindex-1"; private static final String SYSTEM_ALIAS_NAME = ".myindex-alias"; private static final SystemIndexDescriptor DESCRIPTOR = SystemIndexDescriptor.builder() diff --git a/server/src/test/java/org/elasticsearch/indices/SystemIndexDescriptorTests.java b/server/src/test/java/org/elasticsearch/indices/SystemIndexDescriptorTests.java index 71239af291ada..7a651dea0c878 100644 --- a/server/src/test/java/org/elasticsearch/indices/SystemIndexDescriptorTests.java +++ b/server/src/test/java/org/elasticsearch/indices/SystemIndexDescriptorTests.java @@ -19,15 +19,26 @@ import org.elasticsearch.xcontent.json.JsonXContent; import java.util.List; +import java.util.Locale; import java.util.Map; import static org.elasticsearch.indices.SystemIndexDescriptor.findDynamicMapping; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; public class SystemIndexDescriptorTests extends ESTestCase { - private static final String MAPPINGS = "{ \"_doc\": { \"_meta\": { \"version\": \"7.4.0\" } } }"; + private static final String MAPPINGS = String.format(Locale.ROOT, """ + { + "_doc": { + "_meta": { + "version": "7.4.0", + "%s": 1 + } + } + } + """, SystemIndexDescriptor.VERSION_META_KEY); /** * Tests the various validation rules that are applied when creating a new system index descriptor. @@ -243,7 +254,6 @@ public void testPriorSystemIndexDescriptorValidation() { } public void testGetDescriptorCompatibleWith() { - final String mappings = "{ \"_doc\": { \"_meta\": { \"version\": \"7.4.0\" } } }"; final SystemIndexDescriptor prior = SystemIndexDescriptor.builder() .setIndexPattern(".system*") .setDescription("system stuff") @@ -251,7 +261,7 @@ public void testGetDescriptorCompatibleWith() { .setAliasName(".system") .setType(Type.INTERNAL_MANAGED) .setSettings(Settings.EMPTY) - .setMappings(mappings) + .setMappings(MAPPINGS) .setVersionMetaKey("version") .setOrigin("system") .setMinimumNodeVersion(Version.V_7_0_0) @@ -263,7 +273,7 @@ public void testGetDescriptorCompatibleWith() { .setAliasName(".system") .setType(Type.INTERNAL_MANAGED) .setSettings(Settings.EMPTY) - .setMappings(mappings) + .setMappings(MAPPINGS) .setVersionMetaKey("version") .setOrigin("system") .setPriorSystemIndexDescriptors(List.of(prior)) @@ -343,6 +353,79 @@ public void testManagedSystemIndexMustHaveMatchingIndexFormat() { assertThat(e.getMessage(), equalTo("Descriptor index format does not match index format in managed settings")); } + public void testUnmanagedIndexMappingsVersion() { + SystemIndexDescriptor indexDescriptor = SystemIndexDescriptor.builder() + .setIndexPattern(".unmanaged-*") + .setDescription("an unmanaged system index") + .setType(Type.INTERNAL_UNMANAGED) + .build(); + + IllegalStateException e = expectThrows(IllegalStateException.class, indexDescriptor::getMappingsVersion); + + assertThat(e.getMessage(), containsString("is not managed so there are no mappings or version")); + } + + // test mapping versions can't be negative + public void testNegativeMappingsVersion() { + int negativeVersion = randomIntBetween(Integer.MIN_VALUE, -1); + String mappings = String.format(Locale.ROOT, """ + { + "_doc": { + "_meta": { + "version": "7.4.0", + "%s": %d + } + } + } + """, SystemIndexDescriptor.VERSION_META_KEY, negativeVersion); + + SystemIndexDescriptor.Builder builder = priorSystemIndexDescriptorBuilder().setMappings(mappings); + + AssertionError e = expectThrows(AssertionError.class, builder::build); + + assertThat(e.getMessage(), equalTo("The mappings version must not be negative")); + } + + public void testHashesIgnoreMappingMetadata() { + String mappingFormatString = """ + { + "_doc": { + "_meta": { + "version": "%s", + "%s": %d + } + }, + "properties": { + "age": { "type": "integer" }, + "email": { "type": "keyword" }, + "name": { "type": "text" } + } + } + """; + + String mappings1 = String.format( + Locale.ROOT, + mappingFormatString, + "8.9.0", + SystemIndexDescriptor.VERSION_META_KEY, + randomIntBetween(1, 10) + ); + String mappings2 = String.format( + Locale.ROOT, + mappingFormatString, + "8.10.0", + SystemIndexDescriptor.VERSION_META_KEY, + randomIntBetween(11, 20) + ); + + SystemIndexDescriptor descriptor1 = priorSystemIndexDescriptorBuilder().setMappings(mappings1).build(); + SystemIndexDescriptor descriptor2 = priorSystemIndexDescriptorBuilder().setMappings(mappings2).build(); + + assertThat(descriptor1.getMappingsVersion().hash(), equalTo(descriptor2.getMappingsVersion().hash())); + assertThat(descriptor1.getMappingsVersion().version(), not(equalTo(descriptor2.getMappingsVersion().version()))); + assertThat(descriptor1.getMappingsNodeVersion(), not(equalTo(descriptor2.getMappingsNodeVersion()))); + } + private SystemIndexDescriptor.Builder priorSystemIndexDescriptorBuilder() { return SystemIndexDescriptor.builder() .setIndexPattern(".system*") diff --git a/server/src/test/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceTests.java b/server/src/test/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceTests.java index 330615aae93f5..b3492b203d354 100644 --- a/server/src/test/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceTests.java +++ b/server/src/test/java/org/elasticsearch/indices/SystemIndexMappingUpdateServiceTests.java @@ -409,7 +409,10 @@ private static XContentBuilder getMappings() { } private static XContentBuilder getMappings(String version) { - return getMappings(builder -> builder.object("_meta", meta -> meta.field("version", version))); + return getMappings(builder -> builder.object("_meta", meta -> { + meta.field("version", version); + meta.field(SystemIndexDescriptor.VERSION_META_KEY, 5); + })); } // Prior to 7.12.0, .tasks had _meta.version: 3 so we need to be sure we can handle that diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncTaskIndexService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncTaskIndexService.java index 4e7a2416c4860..be6c1a29bcc6f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncTaskIndexService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncTaskIndexService.java @@ -88,6 +88,7 @@ public final class AsyncTaskIndexService> { public static final String RESPONSE_HEADERS_FIELD = "response_headers"; public static final String EXPIRATION_TIME_FIELD = "expiration_time"; public static final String RESULT_FIELD = "result"; + private static final int ASYNC_TASK_INDEX_MAPPINGS_VERSION = 0; // Usually the settings, mappings and system index descriptor below // would be co-located with the SystemIndexPlugin implementation, @@ -110,6 +111,7 @@ private static XContentBuilder mappings() { .startObject(SINGLE_MAPPING_NAME) .startObject("_meta") .field("version", Version.CURRENT) + .field(SystemIndexDescriptor.VERSION_META_KEY, ASYNC_TASK_INDEX_MAPPINGS_VERSION) .endObject() .field("dynamic", "strict") .startObject("properties") diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlConfigIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlConfigIndex.java index 2499734672053..da905ef5efdee 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlConfigIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlConfigIndex.java @@ -12,12 +12,15 @@ import org.elasticsearch.index.IndexSettings; import org.elasticsearch.xpack.core.template.TemplateUtils; +import java.util.Map; + public final class MlConfigIndex { private static final String INDEX_NAME = ".ml-config"; private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; public static final int CONFIG_INDEX_MAX_RESULTS_WINDOW = 10_000; + public static final int CONFIG_INDEX_MAPPINGS_VERSION = 1; /** * The name of the index where job, datafeed and analytics configuration is stored @@ -29,7 +32,12 @@ public static String indexName() { } public static String mapping() { - return TemplateUtils.loadTemplate("/ml/config_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE); + return TemplateUtils.loadTemplate( + "/ml/config_index_mappings.json", + Version.CURRENT.toString(), + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(CONFIG_INDEX_MAPPINGS_VERSION)) + ); } public static Settings settings() { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlMetaIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlMetaIndex.java index a72a051414677..9190be89ee1e0 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlMetaIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlMetaIndex.java @@ -11,10 +11,13 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.xpack.core.template.TemplateUtils; +import java.util.Map; + public final class MlMetaIndex { private static final String INDEX_NAME = ".ml-meta"; private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; + private static final int META_INDEX_MAPPINGS_VERSION = 1; /** * Where to store the ml info in Elasticsearch - must match what's @@ -27,7 +30,12 @@ public static String indexName() { } public static String mapping() { - return TemplateUtils.loadTemplate("/ml/meta_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE); + return TemplateUtils.loadTemplate( + "/ml/meta_index_mappings.json", + Version.CURRENT.toString(), + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(META_INDEX_MAPPINGS_VERSION)) + ); } public static Settings settings() { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlStatsIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlStatsIndex.java index 76234954b4107..83c7a3fe45a09 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlStatsIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlStatsIndex.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils; import java.util.Locale; +import java.util.Map; /** * Describes the indices where ML is storing various stats about the users jobs. @@ -25,6 +26,7 @@ public class MlStatsIndex { public static final String TEMPLATE_NAME = ".ml-stats"; private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; + public static final int STATS_INDEX_MAPPINGS_VERSION = 1; private MlStatsIndex() {} @@ -36,7 +38,12 @@ public static String wrappedMapping() { } public static String mapping() { - return TemplateUtils.loadTemplate("/ml/stats_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE); + return TemplateUtils.loadTemplate( + "/ml/stats_index_mappings.json", + Version.CURRENT.toString(), + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(STATS_INDEX_MAPPINGS_VERSION)) + ); } public static String indexPattern() { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/annotations/AnnotationIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/annotations/AnnotationIndex.java index c509e52675e38..745e50c920288 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/annotations/AnnotationIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/annotations/AnnotationIndex.java @@ -31,6 +31,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils; import java.util.List; +import java.util.Map; import java.util.SortedMap; import static java.lang.Thread.currentThread; @@ -56,6 +57,7 @@ public class AnnotationIndex { public static final List OLD_INDEX_NAMES = List.of(".ml-annotations-6"); private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; + public static final int ANNOTATION_INDEX_MAPPINGS_VERSION = 1; /** * Create the .ml-annotations-6 index with correct mappings if it does not already exist. This index is read and written by the UI @@ -102,7 +104,8 @@ public static void createAnnotationsIndexIfNecessary( client, state, masterNodeTimeout, - finalListener + finalListener, + ANNOTATION_INDEX_MAPPINGS_VERSION ), finalListener::onFailure ); @@ -208,6 +211,11 @@ public static void createAnnotationsIndexIfNecessary( } public static String annotationsMapping() { - return TemplateUtils.loadTemplate("/ml/annotations_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE); + return TemplateUtils.loadTemplate( + "/ml/annotations_index_mappings.json", + Version.CURRENT.toString(), + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(ANNOTATION_INDEX_MAPPINGS_VERSION)) + ); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/persistence/InferenceIndexConstants.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/persistence/InferenceIndexConstants.java index aa8fa7c88e719..1e60da895c0e7 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/persistence/InferenceIndexConstants.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/persistence/InferenceIndexConstants.java @@ -12,6 +12,8 @@ import org.elasticsearch.xcontent.ParseField; import org.elasticsearch.xpack.core.template.TemplateUtils; +import java.util.Map; + /** * Class containing the index constants so that the index version, name, and prefix are available to a wider audience. */ @@ -44,9 +46,15 @@ public final class InferenceIndexConstants { private static final String NATIVE_LATEST_INDEX = NATIVE_INDEX_PREFIX + NATIVE_INDEX_VERSION; private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; + public static final int INFERENCE_INDEX_MAPPINGS_VERSION = 1; public static String mapping() { - return TemplateUtils.loadTemplate("/ml/inference_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE); + return TemplateUtils.loadTemplate( + "/ml/inference_index_mappings.json", + Version.CURRENT.toString(), + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(INFERENCE_INDEX_MAPPINGS_VERSION)) + ); } public static String nativeDefinitionStore() { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/AnomalyDetectorsIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/AnomalyDetectorsIndex.java index 0dbed16d3b821..29ac3359c870b 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/AnomalyDetectorsIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/AnomalyDetectorsIndex.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils; import java.util.Locale; +import java.util.Map; import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; @@ -29,6 +30,7 @@ public final class AnomalyDetectorsIndex { private static final String RESULTS_MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; private static final String RESOURCE_PATH = "/ml/anomalydetection/"; + public static final int RESULTS_INDEX_MAPPINGS_VERSION = 1; private AnomalyDetectorsIndex() {} @@ -136,7 +138,8 @@ public static String resultsMapping() { return TemplateUtils.loadTemplate( RESOURCE_PATH + "results_index_mappings.json", Version.CURRENT.toString(), - RESULTS_MAPPINGS_VERSION_VARIABLE + RESULTS_MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(RESULTS_INDEX_MAPPINGS_VERSION)) ); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java index 1bb88f4bc4773..1dde9dc6075d0 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java @@ -9,7 +9,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRunnable; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction; @@ -22,6 +21,7 @@ import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.Index; +import org.elasticsearch.indices.SystemIndexDescriptor; import org.elasticsearch.plugins.MapperPlugin; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.Transports; @@ -100,7 +100,7 @@ public class ElasticsearchMappings { private ElasticsearchMappings() {} - static String[] mappingRequiresUpdate(ClusterState state, String[] concreteIndices, Version minVersion) { + static String[] mappingRequiresUpdate(ClusterState state, String[] concreteIndices, int minVersion) { List indicesToUpdate = new ArrayList<>(); Map currentMapping = state.metadata() @@ -113,22 +113,26 @@ static String[] mappingRequiresUpdate(ClusterState state, String[] concreteIndic @SuppressWarnings("unchecked") Map meta = (Map) metadata.sourceAsMap().get("_meta"); if (meta != null) { - String versionString = (String) meta.get("version"); - if (versionString == null) { - logger.info("Version of mappings for [{}] not found, recreating", index); + Integer systemIndexMappingsVersion = (Integer) meta.get(SystemIndexDescriptor.VERSION_META_KEY); + if (systemIndexMappingsVersion == null) { + logger.info("System index mappings version for [{}] not found, recreating", index); indicesToUpdate.add(index); continue; } - Version mappingVersion = Version.fromString(versionString); - - if (mappingVersion.onOrAfter(minVersion)) { + if (systemIndexMappingsVersion >= minVersion) { continue; } else { - logger.info("Mappings for [{}] are outdated [{}], updating it[{}].", index, mappingVersion, Version.CURRENT); + logger.info( + "Mappings for [{}] are outdated [{}], updating it[{}].", + index, + systemIndexMappingsVersion, + minVersion + ); indicesToUpdate.add(index); continue; } + } else { logger.info("Version of mappings for [{}] not found, recreating", index); indicesToUpdate.add(index); @@ -153,7 +157,8 @@ public static void addDocMappingIfMissing( Client client, ClusterState state, TimeValue masterNodeTimeout, - ActionListener listener + ActionListener listener, + int minVersion ) { IndexAbstraction indexAbstraction = state.metadata().getIndicesLookup().get(alias); if (indexAbstraction == null) { @@ -167,7 +172,7 @@ public static void addDocMappingIfMissing( protected void doRun() throws Exception { String[] concreteIndices = indexAbstraction.getIndices().stream().map(Index::getName).toArray(String[]::new); - final String[] indicesThatRequireAnUpdate = mappingRequiresUpdate(state, concreteIndices, Version.CURRENT); + final String[] indicesThatRequireAnUpdate = mappingRequiresUpdate(state, concreteIndices, minVersion); if (indicesThatRequireAnUpdate.length > 0) { String mapping = mappingSupplier.get(); PutMappingRequest putMappingRequest = new PutMappingRequest(indicesThatRequireAnUpdate); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/notifications/NotificationsIndex.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/notifications/NotificationsIndex.java index 11c4ec2aa0b77..06a923cd9d275 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/notifications/NotificationsIndex.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/notifications/NotificationsIndex.java @@ -9,12 +9,15 @@ import org.elasticsearch.Version; import org.elasticsearch.xpack.core.template.TemplateUtils; +import java.util.Map; + public final class NotificationsIndex { public static final String NOTIFICATIONS_INDEX = ".ml-notifications-000002"; private static final String RESOURCE_PATH = "/ml/"; private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version"; + private static final int NOTIFICATIONS_INDEX_MAPPINGS_VERSION = 1; private NotificationsIndex() {} @@ -22,7 +25,8 @@ public static String mapping() { return TemplateUtils.loadTemplate( RESOURCE_PATH + "notifications_index_mappings.json", Version.CURRENT.toString(), - MAPPINGS_VERSION_VARIABLE + MAPPINGS_VERSION_VARIABLE, + Map.of("xpack.ml.managed.index.version", Integer.toString(NOTIFICATIONS_INDEX_MAPPINGS_VERSION)) ); } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappingsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappingsTests.java index cf9708505d075..d95c94801e52a 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappingsTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappingsTests.java @@ -23,9 +23,9 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.get.GetResult; +import org.elasticsearch.indices.SystemIndexDescriptor; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.VersionUtils; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentParser; @@ -130,25 +130,45 @@ public void testMappingRequiresUpdateNoMapping() { ClusterState cs = csBuilder.build(); String[] indices = new String[] { "no_index" }; - assertArrayEquals(new String[] { "no_index" }, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + assertArrayEquals(new String[] { "no_index" }, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); } public void testMappingRequiresUpdateNullMapping() { ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("null_mapping", null)); String[] indices = new String[] { "null_index" }; - assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); } public void testMappingRequiresUpdateNoVersion() { ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("no_version_field", "NO_VERSION_FIELD")); String[] indices = new String[] { "no_version_field" }; - assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); } public void testMappingRequiresUpdateRecentMappingVersion() { - ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_current", Version.CURRENT.toString())); - String[] indices = new String[] { "version_current" }; - assertArrayEquals(new String[] {}, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_current", Version.CURRENT.toString()) + ); + String[] indices = new String[] { "version_current" }; + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_current", Version.CURRENT.toString()), + Collections.singletonMap(SystemIndexDescriptor.VERSION_META_KEY, 1) + ); + String[] indices = new String[] { "version_current" }; + assertArrayEquals(new String[] {}, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_current", Version.CURRENT.toString()), + Collections.singletonMap(SystemIndexDescriptor.VERSION_META_KEY, 1) + ); + String[] indices = new String[] { "version_current" }; + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 2)); + } } public void testMappingRequiresUpdateMaliciousMappingVersion() { @@ -156,28 +176,53 @@ public void testMappingRequiresUpdateMaliciousMappingVersion() { Collections.singletonMap("version_current", Collections.singletonMap("nested", "1.0")) ); String[] indices = new String[] { "version_nested" }; - assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); } public void testMappingRequiresUpdateBogusMappingVersion() { ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_bogus", "0.0")); String[] indices = new String[] { "version_bogus" }; - assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, Version.CURRENT)); + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); } public void testMappingRequiresUpdateNewerMappingVersion() { - ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_newer", Version.CURRENT)); - String[] indices = new String[] { "version_newer" }; - assertArrayEquals(new String[] {}, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, VersionUtils.getPreviousVersion())); + { + ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_newer", 2)); + String[] indices = new String[] { "version_newer" }; + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_newer", Version.CURRENT), + Collections.singletonMap(SystemIndexDescriptor.VERSION_META_KEY, 2) + ); + String[] indices = new String[] { "version_newer" }; + assertArrayEquals(new String[] {}, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_newer", Version.CURRENT), + Collections.singletonMap(SystemIndexDescriptor.VERSION_META_KEY, 1) + ); + String[] indices = new String[] { "version_newer" }; + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 2)); + } } public void testMappingRequiresUpdateNewerMappingVersionMinor() { - ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_newer_minor", Version.CURRENT)); - String[] indices = new String[] { "version_newer_minor" }; - assertArrayEquals( - new String[] {}, - ElasticsearchMappings.mappingRequiresUpdate(cs, indices, VersionUtils.getPreviousMinorVersion()) - ); + { + ClusterState cs = getClusterStateWithMappingsWithMetadata(Collections.singletonMap("version_newer_minor", 1)); + String[] indices = new String[] { "version_newer_minor" }; + assertArrayEquals(indices, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } + { + ClusterState cs = getClusterStateWithMappingsWithMetadata( + Collections.singletonMap("version_newer_minor", Version.CURRENT), + Collections.singletonMap(SystemIndexDescriptor.VERSION_META_KEY, 1) + ); + String[] indices = new String[] { "version_newer_minor" }; + assertArrayEquals(new String[] {}, ElasticsearchMappings.mappingRequiresUpdate(cs, indices, 1)); + } } @SuppressWarnings({ "unchecked" }) @@ -200,7 +245,8 @@ public void testAddDocMappingIfMissing() { client, clusterState, MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT, - ActionTestUtils.assertNoFailureListener(Assert::assertTrue) + ActionTestUtils.assertNoFailureListener(Assert::assertTrue), + 1 ); ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(PutMappingRequest.class); @@ -215,6 +261,10 @@ public void testAddDocMappingIfMissing() { } private ClusterState getClusterStateWithMappingsWithMetadata(Map namesAndVersions) { + return getClusterStateWithMappingsWithMetadata(namesAndVersions, null); + } + + private ClusterState getClusterStateWithMappingsWithMetadata(Map namesAndVersions, Map metaData) { Metadata.Builder metadataBuilder = Metadata.builder(); for (Map.Entry entry : namesAndVersions.entrySet()) { @@ -236,6 +286,9 @@ private ClusterState getClusterStateWithMappingsWithMetadata(Map if (version != null && version.equals("NO_VERSION_FIELD") == false) { meta.put("version", version); } + if (metaData != null) { + metaData.forEach((k, v) -> meta.putIfAbsent(k, v)); + } mapping.put("_meta", meta); indexMetadata.putMapping(new MappingMetadata("_doc", mapping)); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/test/TestRestrictedIndices.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/test/TestRestrictedIndices.java index 38bdb8ef18350..92c3a65ffeaa3 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/test/TestRestrictedIndices.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/test/TestRestrictedIndices.java @@ -266,6 +266,7 @@ private static XContentBuilder mockMappings() { .startObject(SINGLE_MAPPING_NAME) .startObject("_meta") .field("version", Version.CURRENT) + .field(SystemIndexDescriptor.VERSION_META_KEY, 0) .endObject() .field("dynamic", "strict") .startObject("properties") diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions-results.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions-results.json index 04e67d6ebe528..88c51a9aef284 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions-results.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions-results.json @@ -10,7 +10,8 @@ }, "mappings": { "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "dynamic": false, "properties": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions.json index 55a6575e15c2a..2b3ecbac92352 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-actions.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "action_id": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-agents.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-agents.json index 7afbd8b3db201..344fe2f5e3a2c 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-agents.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-agents.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "access_api_key_id": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-artifacts.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-artifacts.json index bb7fbda297db2..4a5f76470d24f 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-artifacts.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-artifacts.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "identifier": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-enrollment-api-keys.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-enrollment-api-keys.json index 2032bee4aaabb..6be455e02825a 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-enrollment-api-keys.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-enrollment-api-keys.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "active": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies-leader.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies-leader.json index 73179d529aae8..7cce4e0d4f53a 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies-leader.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies-leader.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "server": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies.json index 3e7031c1eab89..44e2e67dd06c3 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-policies.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "coordinator_idx": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-secrets.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-secrets.json index 684dfc1c7928a..6d16098e38049 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-secrets.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-secrets.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "value": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/fleet-servers.json b/x-pack/plugin/core/template-resources/src/main/resources/fleet-servers.json index b9b9a8f5b5249..8ddd5e7e0693e 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/fleet-servers.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/fleet-servers.json @@ -6,7 +6,8 @@ "_doc" : { "dynamic": false, "_meta": { - "version": "${fleet.version}" + "version": "${fleet.version}", + "managed_index_mappings_version": ${fleet.managed.index.version} }, "properties": { "agent": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/annotations_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/annotations_index_mappings.json index 1292ce06e3044..42efa741dd99d 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/annotations_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/annotations_index_mappings.json @@ -1,7 +1,8 @@ { "_doc": { "_meta" : { - "version" : "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic" : false, "properties" : { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/anomalydetection/results_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/anomalydetection/results_index_mappings.json index 89389012664b2..4415afe50a998 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/anomalydetection/results_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/anomalydetection/results_index_mappings.json @@ -1,6 +1,7 @@ { "_meta" : { - "version" : "${xpack.ml.version}" + "version" : "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic_templates" : [ { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/config_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/config_index_mappings.json index 7de21b4901f1a..811810f5d0f2f 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/config_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/config_index_mappings.json @@ -1,7 +1,8 @@ { "_doc" : { "_meta" : { - "version" : "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic_templates" : [ { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/inference_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/inference_index_mappings.json index d2e73d494bcc3..7ff961a0aac9c 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/inference_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/inference_index_mappings.json @@ -1,7 +1,8 @@ { "_doc": { "_meta": { - "version": "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic": false, "properties": { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/meta_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/meta_index_mappings.json index f78414f53ea4f..4606cb0d75d8f 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/meta_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/meta_index_mappings.json @@ -1,7 +1,8 @@ { "_doc": { "_meta": { - "version": "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic_templates": [ { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/notifications_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/notifications_index_mappings.json index e0e44d8b230f4..b2135d2c6e76e 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/notifications_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/notifications_index_mappings.json @@ -1,6 +1,7 @@ { "_meta" : { - "version" : "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic" : "false", "properties" : { diff --git a/x-pack/plugin/core/template-resources/src/main/resources/ml/stats_index_mappings.json b/x-pack/plugin/core/template-resources/src/main/resources/ml/stats_index_mappings.json index 711bfe1f9c1dc..8c151cb38c1b3 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/ml/stats_index_mappings.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/ml/stats_index_mappings.json @@ -1,6 +1,7 @@ { "_meta": { - "version" : "${xpack.ml.version}" + "version": "${xpack.ml.version}", + "managed_index_mappings_version": ${xpack.ml.managed.index.version} }, "dynamic": false, "properties" : { diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/rules/QueryRulesIndexService.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/rules/QueryRulesIndexService.java index d629700b7c61a..de823ab2a6ce2 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/rules/QueryRulesIndexService.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/rules/QueryRulesIndexService.java @@ -63,6 +63,7 @@ public class QueryRulesIndexService { public static final String QUERY_RULES_ALIAS_NAME = ".query-rules"; public static final String QUERY_RULES_CONCRETE_INDEX_NAME = ".query-rules-1"; public static final String QUERY_RULES_INDEX_NAME_PATTERN = ".query-rules-*"; + private static final int QUERY_RULES_INDEX_MAPPINGS_VERSION = 1; private final Client clientWithOrigin; private final ClusterSettings clusterSettings; @@ -107,6 +108,7 @@ private static XContentBuilder getIndexMappings() { { builder.startObject("_meta"); builder.field("version", Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, QUERY_RULES_INDEX_MAPPINGS_VERSION); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/search/SearchApplicationIndexService.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/search/SearchApplicationIndexService.java index b4917607feb88..681a2ff5028a3 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/search/SearchApplicationIndexService.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/search/SearchApplicationIndexService.java @@ -94,6 +94,7 @@ public class SearchApplicationIndexService { public static final String SEARCH_APPLICATION_ALIAS_NAME = ".search-app"; public static final String SEARCH_APPLICATION_CONCRETE_INDEX_NAME = ".search-app-1"; public static final String SEARCH_APPLICATION_INDEX_NAME_PATTERN = ".search-app-*"; + private static final int SEARCH_APPLICATION_INDEX_MAPPINGS_VERSION = 1; // The client to perform any operations on user indices (alias, ...). private final Client client; @@ -152,6 +153,7 @@ private static XContentBuilder getIndexMappings() { { builder.startObject("_meta"); builder.field("version", Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, SEARCH_APPLICATION_INDEX_MAPPINGS_VERSION); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java index 4afc2bb44793a..009e17bd79e6b 100644 --- a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java +++ b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/Fleet.java @@ -89,6 +89,15 @@ public class Fleet extends Plugin implements SystemIndexPlugin { private static final String VERSION_KEY = "version"; private static final String MAPPING_VERSION_VARIABLE = "fleet.version"; private static final List ALLOWED_PRODUCTS = List.of("kibana", "fleet"); + private static final int FLEET_ACTIONS_MAPPINGS_VERSION = 1; + private static final int FLEET_AGENTS_MAPPINGS_VERSION = 1; + private static final int FLEET_ENROLLMENT_API_KEYS_MAPPINGS_VERSION = 1; + private static final int FLEET_SECRETS_MAPPINGS_VERSION = 1; + private static final int FLEET_POLICIES_MAPPINGS_VERSION = 1; + private static final int FLEET_POLICIES_LEADER_MAPPINGS_VERSION = 1; + private static final int FLEET_SERVERS_MAPPINGS_VERSION = 1; + private static final int FLEET_ARTIFACTS_MAPPINGS_VERSION = 1; + private static final int FLEET_ACTIONS_RESULTS_MAPPINGS_VERSION = 1; @Override public Collection createComponents( @@ -149,7 +158,7 @@ public String getFeatureDescription() { private SystemIndexDescriptor fleetActionsSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-actions.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-actions.json", FLEET_ACTIONS_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -167,7 +176,7 @@ private SystemIndexDescriptor fleetActionsSystemIndexDescriptor() { private SystemIndexDescriptor fleetAgentsSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-agents.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-agents.json", FLEET_AGENTS_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -185,7 +194,10 @@ private SystemIndexDescriptor fleetAgentsSystemIndexDescriptor() { private SystemIndexDescriptor fleetEnrollmentApiKeysSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-enrollment-api-keys.json"), XContentType.JSON); + request.source( + loadTemplateSource("/fleet-enrollment-api-keys.json", FLEET_ENROLLMENT_API_KEYS_MAPPINGS_VERSION), + XContentType.JSON + ); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -203,7 +215,7 @@ private SystemIndexDescriptor fleetEnrollmentApiKeysSystemIndexDescriptor() { private SystemIndexDescriptor fleetSecretsSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-secrets.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-secrets.json", FLEET_SECRETS_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.INTERNAL_MANAGED) .setOrigin(FLEET_ORIGIN) @@ -219,7 +231,7 @@ private SystemIndexDescriptor fleetSecretsSystemIndexDescriptor() { private SystemIndexDescriptor fleetPoliciesSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-policies.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-policies.json", FLEET_POLICIES_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -237,7 +249,7 @@ private SystemIndexDescriptor fleetPoliciesSystemIndexDescriptor() { private SystemIndexDescriptor fleetPoliciesLeaderSystemIndexDescriptor() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-policies-leader.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-policies-leader.json", FLEET_POLICIES_LEADER_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -255,7 +267,7 @@ private SystemIndexDescriptor fleetPoliciesLeaderSystemIndexDescriptor() { private SystemIndexDescriptor fleetServersSystemIndexDescriptors() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-servers.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-servers.json", FLEET_SERVERS_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -273,7 +285,7 @@ private SystemIndexDescriptor fleetServersSystemIndexDescriptors() { private SystemIndexDescriptor fleetArtifactsSystemIndexDescriptors() { PutIndexTemplateRequest request = new PutIndexTemplateRequest(); - request.source(loadTemplateSource("/fleet-artifacts.json"), XContentType.JSON); + request.source(loadTemplateSource("/fleet-artifacts.json", FLEET_ARTIFACTS_MAPPINGS_VERSION), XContentType.JSON); return SystemIndexDescriptor.builder() .setType(Type.EXTERNAL_MANAGED) @@ -290,7 +302,7 @@ private SystemIndexDescriptor fleetArtifactsSystemIndexDescriptors() { } private SystemDataStreamDescriptor fleetActionsResultsDescriptor() { - final String source = loadTemplateSource("/fleet-actions-results.json"); + final String source = loadTemplateSource("/fleet-actions-results.json", FLEET_ACTIONS_RESULTS_MAPPINGS_VERSION); try (XContentParser parser = XContentType.JSON.xContent().createParser(XContentParserConfiguration.EMPTY, source)) { ComposableIndexTemplate composableIndexTemplate = ComposableIndexTemplate.parse(parser); return new SystemDataStreamDescriptor( @@ -345,8 +357,13 @@ public void cleanUpFeature(ClusterService clusterService, Client client, ActionL } } - private String loadTemplateSource(String resource) { - return TemplateUtils.loadTemplate(resource, Version.CURRENT.toString(), MAPPING_VERSION_VARIABLE); + private String loadTemplateSource(String resource, int mappingsVersion) { + return TemplateUtils.loadTemplate( + resource, + Version.CURRENT.toString(), + MAPPING_VERSION_VARIABLE, + Map.of("fleet.managed.index.version", Integer.toString(mappingsVersion)) + ); } @Override diff --git a/x-pack/plugin/logstash/src/main/java/org/elasticsearch/xpack/logstash/Logstash.java b/x-pack/plugin/logstash/src/main/java/org/elasticsearch/xpack/logstash/Logstash.java index 4eb9d058aa2dc..ecba96432839b 100644 --- a/x-pack/plugin/logstash/src/main/java/org/elasticsearch/xpack/logstash/Logstash.java +++ b/x-pack/plugin/logstash/src/main/java/org/elasticsearch/xpack/logstash/Logstash.java @@ -58,6 +58,7 @@ public class Logstash extends Plugin implements SystemIndexPlugin { public static final String LOGSTASH_CONCRETE_INDEX_NAME = ".logstash"; public static final String LOGSTASH_INDEX_NAME_PATTERN = LOGSTASH_CONCRETE_INDEX_NAME + "*"; + public static final int LOGSTASH_INDEX_MAPPINGS_VERSION = 1; static final LicensedFeature.Momentary LOGSTASH_FEATURE = LicensedFeature.momentary(null, "logstash", License.OperationMode.STANDARD); @@ -121,6 +122,7 @@ private XContentBuilder getIndexMappings() { { builder.startObject("_meta"); builder.field("logstash-version", Version.CURRENT); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, LOGSTASH_INDEX_MAPPINGS_VERSION); builder.endObject(); } { diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java index a458c3df86910..5e033278242ad 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java @@ -313,7 +313,8 @@ private void clearJobFinishedTime( client, clusterState, masterNodeTimeout, - mappingsUpdatedListener + mappingsUpdatedListener, + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutDataFrameAnalyticsAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutDataFrameAnalyticsAction.java index bff2d7dc69439..9ae73224a698d 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutDataFrameAnalyticsAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutDataFrameAnalyticsAction.java @@ -273,7 +273,8 @@ private void updateDocMappingAndPutConfig( client, clusterState, masterNodeTimeout, - ActionListener.wrap(unused -> configProvider.put(config, headers, masterNodeTimeout, auditingListener), listener::onFailure) + ActionListener.wrap(unused -> configProvider.put(config, headers, masterNodeTimeout, auditingListener), listener::onFailure), + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportRevertModelSnapshotAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportRevertModelSnapshotAction.java index ecfbec71ab285..b12d1ffd75287 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportRevertModelSnapshotAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportRevertModelSnapshotAction.java @@ -169,7 +169,8 @@ protected void masterOperation( client, state, request.masterNodeTimeout(), - configMappingUpdateListener + configMappingUpdateListener, + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ), listener::onFailure ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpdateDataFrameAnalyticsAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpdateDataFrameAnalyticsAction.java index c542213029289..921adf3924dde 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpdateDataFrameAnalyticsAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpdateDataFrameAnalyticsAction.java @@ -110,7 +110,8 @@ protected void masterOperation( client, state, request.masterNodeTimeout(), - ActionListener.wrap(bool -> doUpdate.run(), listener::onFailure) + ActionListener.wrap(bool -> doUpdate.run(), listener::onFailure), + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpgradeJobModelSnapshotAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpgradeJobModelSnapshotAction.java index a97ce5628da23..bd6b55d10af5a 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpgradeJobModelSnapshotAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportUpgradeJobModelSnapshotAction.java @@ -174,7 +174,8 @@ protected void masterOperation(Task task, Request request, ClusterState state, A client, state, request.masterNodeTimeout(), - configIndexMappingUpdaterListener + configIndexMappingUpdaterListener, + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ), listener::onFailure ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/datafeed/DatafeedManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/datafeed/DatafeedManager.java index 7fcf7cf980246..ef8b589735585 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/datafeed/DatafeedManager.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/datafeed/DatafeedManager.java @@ -239,7 +239,8 @@ public void updateDatafeed( client, state, request.masterNodeTimeout(), - ActionListener.wrap(bool -> doUpdate.run(), listener::onFailure) + ActionListener.wrap(bool -> doUpdate.run(), listener::onFailure), + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); } @@ -332,7 +333,8 @@ private void putDatafeed( client, clusterState, request.masterNodeTimeout(), - ActionListener.wrap(mappingsUpdated, listener::onFailure) + ActionListener.wrap(mappingsUpdated, listener::onFailure), + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); }; diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/dataframe/DataFrameAnalyticsManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/dataframe/DataFrameAnalyticsManager.java index e699f071e2cfc..718b70fb8801b 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/dataframe/DataFrameAnalyticsManager.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/dataframe/DataFrameAnalyticsManager.java @@ -165,7 +165,8 @@ private void createStatsIndexAndUpdateMappingsIfNecessary( clientToUse, clusterState, masterNodeTimeout, - listener + listener, + MlStatsIndex.STATS_INDEX_MAPPINGS_VERSION ), listener::onFailure ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/TrainedModelStatsService.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/TrainedModelStatsService.java index 6376b21f07c06..b6c6f0865aad8 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/TrainedModelStatsService.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/TrainedModelStatsService.java @@ -262,7 +262,8 @@ private void createStatsIndexIfNecessary() { client, clusterState, MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT, - listener + listener, + MlStatsIndex.STATS_INDEX_MAPPINGS_VERSION ), listener::onFailure ) diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java index c3ffd841eadf3..ba3a52df5cdb6 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java @@ -282,7 +282,8 @@ public void onFailure(Exception e) { client, state, request.masterNodeTimeout(), - putJobListener + putJobListener, + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ), putJobListener::onFailure ); @@ -353,7 +354,8 @@ public void updateJob(UpdateJobAction.Request request, ActionListener doUpdate.run(), actionListener::onFailure) + ActionListener.wrap(bool -> doUpdate.run(), actionListener::onFailure), + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION ); if (request.getJobUpdate().getGroups() != null && request.getJobUpdate().getGroups().isEmpty() == false) { diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java index 9170950778444..f09b3166964f5 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java @@ -574,7 +574,8 @@ public void openJob( client, clusterState, masterNodeTimeout, - resultsMappingUpdateHandler + resultsMappingUpdateHandler, + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION ), e -> { // Due to a bug in 7.9.0 it's possible that the annotations index already has incorrect mappings @@ -586,7 +587,8 @@ public void openJob( client, clusterState, masterNodeTimeout, - resultsMappingUpdateHandler + resultsMappingUpdateHandler, + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION ); } ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/snapshot/upgrader/SnapshotUpgradeTaskExecutor.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/snapshot/upgrader/SnapshotUpgradeTaskExecutor.java index 8119deb7674f9..69b926876302a 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/snapshot/upgrader/SnapshotUpgradeTaskExecutor.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/snapshot/upgrader/SnapshotUpgradeTaskExecutor.java @@ -198,7 +198,8 @@ protected void nodeOperation(AllocatedPersistentTask task, SnapshotUpgradeTaskPa client, clusterState, MlTasks.PERSISTENT_TASK_MASTER_NODE_TIMEOUT, - resultsMappingUpdateHandler + resultsMappingUpdateHandler, + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION ), e -> { // Due to a bug in 7.9.0 it's possible that the annotations index already has incorrect mappings @@ -210,7 +211,8 @@ protected void nodeOperation(AllocatedPersistentTask task, SnapshotUpgradeTaskPa client, clusterState, MlTasks.PERSISTENT_TASK_MASTER_NODE_TIMEOUT, - resultsMappingUpdateHandler + resultsMappingUpdateHandler, + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION ); } ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/task/OpenJobPersistentTasksExecutor.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/task/OpenJobPersistentTasksExecutor.java index 8b990f22c7b38..7a027e2c5cfa4 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/task/OpenJobPersistentTasksExecutor.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/task/OpenJobPersistentTasksExecutor.java @@ -277,7 +277,8 @@ protected void nodeOperation(AllocatedPersistentTask task, OpenJobAction.JobPara client, clusterState, PERSISTENT_TASK_MASTER_NODE_TIMEOUT, - resultsMappingUpdateHandler + resultsMappingUpdateHandler, + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION ); } diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java index 9866f5e3e2a84..35c7e703bf008 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java @@ -251,6 +251,7 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng * This affects the system searchable snapshot cache index (not the searchable snapshot index itself) */ public static final String DATA_TIERS_CACHE_INDEX_PREFERENCE = String.join(",", DataTier.DATA_CONTENT, DataTier.DATA_HOT); + private static final int SEARCHABLE_SNAPSHOTS_INDEX_MAPPINGS_VERSION = 1; private volatile Supplier repositoriesServiceSupplier; private final SetOnce blobStoreCacheService = new SetOnce<>(); @@ -613,6 +614,7 @@ private static XContentBuilder getIndexMappings() { { builder.startObject("_meta"); builder.field("version", Version.CURRENT); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, SEARCHABLE_SNAPSHOTS_INDEX_MAPPINGS_VERSION); builder.endObject(); } { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java index 1277d99c2acca..bdc25098f1760 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java @@ -264,7 +264,7 @@ private boolean checkIndexMappingUpToDate(ClusterState clusterState) { * * ...which is true if the mappings have been updated. */ - return checkIndexMappingVersionMatches(clusterState, descriptor.getMappingVersion()::onOrBefore); + return checkIndexMappingVersionMatches(clusterState, descriptor.getMappingsNodeVersion()::onOrBefore); } private boolean checkIndexMappingVersionMatches(ClusterState clusterState, Predicate predicate) { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecuritySystemIndices.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecuritySystemIndices.java index c3128fff5505e..594726b47a85e 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecuritySystemIndices.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecuritySystemIndices.java @@ -37,8 +37,11 @@ public class SecuritySystemIndices { public static final int INTERNAL_MAIN_INDEX_FORMAT = 6; + private static final int INTERNAL_MAIN_INDEX_MAPPINGS_FORMAT = 1; private static final int INTERNAL_TOKENS_INDEX_FORMAT = 7; + private static final int INTERNAL_TOKENS_INDEX_MAPPINGS_FORMAT = 1; private static final int INTERNAL_PROFILE_INDEX_FORMAT = 8; + private static final int INTERNAL_PROFILE_INDEX_MAPPINGS_FORMAT = 1; public static final String SECURITY_MAIN_ALIAS = ".security"; private static final String MAIN_INDEX_CONCRETE_NAME = ".security-7"; @@ -142,6 +145,7 @@ private XContentBuilder getMainIndexMappings() { { builder.startObject("_meta"); builder.field(SECURITY_VERSION_STRING, Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, INTERNAL_MAIN_INDEX_MAPPINGS_FORMAT); builder.endObject(); builder.field("dynamic", "strict"); @@ -627,6 +631,7 @@ private static XContentBuilder getTokenIndexMappings() { { builder.startObject("_meta"); builder.field(SECURITY_VERSION_STRING, Version.CURRENT); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, INTERNAL_TOKENS_INDEX_MAPPINGS_FORMAT); builder.endObject(); builder.field("dynamic", "strict"); @@ -838,6 +843,7 @@ private XContentBuilder getProfileIndexMappings() { { builder.startObject("_meta"); builder.field(SECURITY_VERSION_STRING, Version.CURRENT.toString()); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, INTERNAL_PROFILE_INDEX_MAPPINGS_FORMAT); builder.endObject(); builder.field("dynamic", "strict"); diff --git a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/persistence/TransformInternalIndex.java b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/persistence/TransformInternalIndex.java index 783aadedcd699..722f37059cc56 100644 --- a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/persistence/TransformInternalIndex.java +++ b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/persistence/TransformInternalIndex.java @@ -87,6 +87,7 @@ public final class TransformInternalIndex { public static final String KEYWORD = "keyword"; public static final String BOOLEAN = "boolean"; public static final String FLATTENED = "flattened"; + public static final int TRANSFORM_INDEX_MAPPINGS_VERSION = 1; public static SystemIndexDescriptor getSystemIndexDescriptor(Settings transformInternalIndexAdditionalSettings) throws IOException { return SystemIndexDescriptor.builder() @@ -357,7 +358,10 @@ private static XContentBuilder addTransformCheckpointMappings(XContentBuilder bu * @throws IOException On write error */ private static XContentBuilder addMetaInformation(XContentBuilder builder) throws IOException { - return builder.startObject("_meta").field("version", Version.CURRENT).endObject(); + return builder.startObject("_meta") + .field("version", Version.CURRENT) + .field(SystemIndexDescriptor.VERSION_META_KEY, TRANSFORM_INDEX_MAPPINGS_VERSION) + .endObject(); } protected static boolean hasLatestVersionedIndex(ClusterState state) { diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java index ca3a68f99d74d..afcc8a2097e94 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java @@ -276,6 +276,8 @@ public class Watcher extends Plugin implements SystemIndexPlugin, ScriptPlugin, ); private static final Logger logger = LogManager.getLogger(Watcher.class); + private static final int WATCHES_INDEX_MAPPINGS_VERSION = 1; + private static final int TRIGGERED_WATCHES_INDEX_MAPPINGS_VERSION = 1; private WatcherIndexingListener listener; private HttpClient httpClient; private BulkProcessor2 bulkProcessor; @@ -876,6 +878,7 @@ private XContentBuilder getWatchesIndexMappings() { { builder.startObject("_meta"); builder.field("version", Version.CURRENT); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, WATCHES_INDEX_MAPPINGS_VERSION); builder.endObject(); } { @@ -967,6 +970,7 @@ private XContentBuilder getTriggeredWatchesIndexMappings() { { builder.startObject("_meta"); builder.field("version", Version.CURRENT); + builder.field(SystemIndexDescriptor.VERSION_META_KEY, TRIGGERED_WATCHES_INDEX_MAPPINGS_VERSION); builder.endObject(); } { diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlMappingsUpgradeIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlMappingsUpgradeIT.java index 39efc221ed129..95d543a0f63ea 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlMappingsUpgradeIT.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlMappingsUpgradeIT.java @@ -10,6 +10,9 @@ import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseException; +import org.elasticsearch.xpack.core.ml.MlConfigIndex; +import org.elasticsearch.xpack.core.ml.annotations.AnnotationIndex; +import org.elasticsearch.xpack.core.ml.job.persistence.AnomalyDetectorsIndex; import org.elasticsearch.xpack.test.rest.IndexMappingTemplateAsserter; import org.elasticsearch.xpack.test.rest.XPackRestTestConstants; import org.elasticsearch.xpack.test.rest.XPackRestTestHelper; @@ -129,6 +132,10 @@ private void assertUpgradedResultsMappings() throws Exception { assertNotNull(indexLevel); assertEquals(Version.CURRENT.toString(), extractValue("mappings._meta.version", indexLevel)); + assertEquals( + AnomalyDetectorsIndex.RESULTS_INDEX_MAPPINGS_VERSION, + extractValue("mappings._meta.managed_index_mappings_version", indexLevel) + ); // TODO: as the years go by, the field we assert on here should be changed // to the most recent field we've added that is NOT of type "keyword" @@ -162,6 +169,10 @@ private void assertUpgradedAnnotationsMappings() throws Exception { assertNotNull(indexLevel); assertEquals(Version.CURRENT.toString(), extractValue("mappings._meta.version", indexLevel)); + assertEquals( + AnnotationIndex.ANNOTATION_INDEX_MAPPINGS_VERSION, + extractValue("mappings._meta.managed_index_mappings_version", indexLevel) + ); // TODO: as the years go by, the field we assert on here should be changed // to the most recent field we've added that would be incorrectly mapped by dynamic @@ -216,6 +227,10 @@ private void assertUpgradedConfigMappings() throws Exception { assertNotNull(indexLevel); assertEquals(Version.CURRENT.toString(), extractValue("mappings._meta.version", indexLevel)); + assertEquals( + MlConfigIndex.CONFIG_INDEX_MAPPINGS_VERSION, + extractValue("mappings._meta.managed_index_mappings_version", indexLevel) + ); // TODO: as the years go by, the field we assert on here should be changed // to the most recent field we've added that is NOT of type "keyword" From 136a60c92a2951f93c4c5ba8ef331953ae1aacd6 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 14:06:34 +1000 Subject: [PATCH 08/21] Mute upgrades.FullClusterRestartIT.testClusterState (#98556) Relates: #98555 --- .../java/org/elasticsearch/upgrades/FullClusterRestartIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java index 5ef9a48a200a3..a9b9e36f1c079 100644 --- a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java @@ -386,6 +386,7 @@ private int createTimeSeriesModeIndex(int replicas) throws IOException { return numDocs; } + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98555") public void testClusterState() throws Exception { if (isRunningAgainstOldCluster()) { XContentBuilder mappingsAndSettings = jsonBuilder(); From faf67f3918cb0f7d1fd610b4da9807cd75663a43 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 15:49:21 +1000 Subject: [PATCH 09/21] Mute testCCSCheckCompatibility (#98559) These tests fail when `TransportVersion.current()` is equal to `TransportVersion.MINIMUM_CCS_VERSION` Relates: #98557 --- .../java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java | 1 + .../xpack/core/termsenum/TransportTermsEnumActionTests.java | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java b/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java index 223dd41c447bb..03b94c1f58b4b 100644 --- a/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java +++ b/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java @@ -527,6 +527,7 @@ public void testMaxResponseSize() { updateClusterSettings(Settings.builder().put("search.max_async_search_response_size", (String) null)); } + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98557") public void testCCSCheckCompatibility() throws Exception { SubmitAsyncSearchRequest request = new SubmitAsyncSearchRequest(new SearchSourceBuilder().query(new DummyQueryBuilder() { @Override diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java index 6cb299312bfd1..e913b879e8442 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java @@ -66,6 +66,7 @@ public void onFailure(final Exception e) { /** * Test that triggering the CCS compatibility check with a query that shouldn't go to the minor before Version.CURRENT works */ + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98557") public void testCCSCheckCompatibility() throws Exception { TermsEnumRequest request = new TermsEnumRequest().field("field").timeout(TimeValue.timeValueSeconds(5)); request.indexFilter(new DummyQueryBuilder() { From bc73bf5e0fe57b5110da2b24bbbdc396111e2e08 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 16:53:36 +1000 Subject: [PATCH 10/21] Mute MlJobSnapshotUpgradeIT (#98561) Relates: #98560 --- .../java/org/elasticsearch/upgrades/MlJobSnapshotUpgradeIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlJobSnapshotUpgradeIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlJobSnapshotUpgradeIT.java index 82d133bf26e11..fa36d2aac7f14 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlJobSnapshotUpgradeIT.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/MlJobSnapshotUpgradeIT.java @@ -66,6 +66,7 @@ protected static void waitForPendingUpgraderTasks() throws Exception { * The purpose of this test is to ensure that when a job is open through a rolling upgrade we upgrade the results * index mappings when it is assigned to an upgraded node even if no other ML endpoint is called after the upgrade */ + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98560") public void testSnapshotUpgrader() throws Exception { Request adjustLoggingLevels = new Request("PUT", "/_cluster/settings"); adjustLoggingLevels.setJsonEntity(""" From 0c35785d22e965183bb1eeec06323041abe43cc6 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 17:16:37 +1000 Subject: [PATCH 11/21] Mute FeatureUpgradeIT (#98563) Relates: #98562 --- .../test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java index 74ba81e9555e2..7c5999a981b69 100644 --- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java +++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java @@ -24,6 +24,7 @@ public class FeatureUpgradeIT extends AbstractRollingTestCase { @SuppressWarnings("unchecked") + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98562") public void testGetFeatureUpgradeStatus() throws Exception { final String systemIndexWarning = "this request accesses system indices: [.tasks], but in a future major version, direct " From d3ac89cc403c3cc651f9129715bae128e736c6b8 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 17 Aug 2023 17:52:30 +1000 Subject: [PATCH 12/21] Mute TransformPersistentTasksExecutorTests (#98565) Relates: #98564 --- .../transforms/TransformPersistentTasksExecutorTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/transform/src/test/java/org/elasticsearch/xpack/transform/transforms/TransformPersistentTasksExecutorTests.java b/x-pack/plugin/transform/src/test/java/org/elasticsearch/xpack/transform/transforms/TransformPersistentTasksExecutorTests.java index f7cb37d1cc56f..4773a00de7567 100644 --- a/x-pack/plugin/transform/src/test/java/org/elasticsearch/xpack/transform/transforms/TransformPersistentTasksExecutorTests.java +++ b/x-pack/plugin/transform/src/test/java/org/elasticsearch/xpack/transform/transforms/TransformPersistentTasksExecutorTests.java @@ -58,6 +58,7 @@ public class TransformPersistentTasksExecutorTests extends ESTestCase { + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98564") public void testNodeVersionAssignment() { DiscoveryNodes.Builder nodes = buildNodes(false, true, true, true, true); ClusterState cs = buildClusterState(nodes); @@ -89,6 +90,7 @@ public void testNodeVersionAssignment() { ); } + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98564") public void testNodeAssignmentProblems() { // no data nodes DiscoveryNodes.Builder nodes = buildNodes(false, false, false, false, true); From 547947d465ac91f41b38ad438a3500a66393be61 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 09:28:34 +0100 Subject: [PATCH 13/21] Specify correct current IndexVersion after 8.10 release (#98574) The current IndexVersion wasn't bumped by the release automation as it should have been --- docs/changelog/98574.yaml | 6 ++++++ .../org/elasticsearch/upgrades/FullClusterRestartIT.java | 1 - .../src/main/java/org/elasticsearch/index/IndexVersion.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 docs/changelog/98574.yaml diff --git a/docs/changelog/98574.yaml b/docs/changelog/98574.yaml new file mode 100644 index 0000000000000..bf016b4c241c8 --- /dev/null +++ b/docs/changelog/98574.yaml @@ -0,0 +1,6 @@ +pr: 98574 +summary: Specify correct current `IndexVersion` after 8.10 release +area: Infra/Core +type: bug +issues: + - 98555 diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java index a9b9e36f1c079..5ef9a48a200a3 100644 --- a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java @@ -386,7 +386,6 @@ private int createTimeSeriesModeIndex(int replicas) throws IOException { return numDocs; } - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98555") public void testClusterState() throws Exception { if (isRunningAgainstOldCluster()) { XContentBuilder mappingsAndSettings = jsonBuilder(); diff --git a/server/src/main/java/org/elasticsearch/index/IndexVersion.java b/server/src/main/java/org/elasticsearch/index/IndexVersion.java index 9f8311bb3963c..90feb9288eb1c 100644 --- a/server/src/main/java/org/elasticsearch/index/IndexVersion.java +++ b/server/src/main/java/org/elasticsearch/index/IndexVersion.java @@ -185,7 +185,7 @@ private static IndexVersion registerIndexVersion(int id, Version luceneVersion, * Detached index versions added below here. */ private static class CurrentHolder { - private static final IndexVersion CURRENT = findCurrent(V_8_10_0); + private static final IndexVersion CURRENT = findCurrent(V_8_11_0); // finds the pluggable current version, or uses the given fallback private static IndexVersion findCurrent(IndexVersion fallback) { From 3ab480fa8756f85dabe841f57349f574f34d2db9 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 10:24:55 +0100 Subject: [PATCH 14/21] Fix tests that break when minimum ccs compatibility == current transport version (#98571) Add a method to get one higher than minimum ccs version, even if the version hasn't been defined yet --- .../resolve/TransportResolveIndexActionTests.java | 10 ++++++---- .../TransportFieldCapabilitiesActionTests.java | 15 ++++++--------- .../action/search/TransportSearchActionTests.java | 9 +++++---- .../elasticsearch/test/TransportVersionUtils.java | 11 ++++++++++- .../xpack/search/AsyncSearchActionIT.java | 4 ++-- .../termsenum/TransportTermsEnumActionTests.java | 9 ++++----- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java index aaf709ef76064..1768f66fea274 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.search.SearchService; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -48,11 +49,12 @@ public void testCCSCompatibilityCheck() throws Exception { .build(); ActionFilters actionFilters = mock(ActionFilters.class); when(actionFilters.filters()).thenReturn(new ActionFilter[0]); + TransportVersion transportVersion = TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); try { TransportService transportService = MockTransportService.createNewService( Settings.EMPTY, VersionInformation.CURRENT, - TransportVersion.current(), + transportVersion, threadPool ); @@ -60,9 +62,9 @@ public void testCCSCompatibilityCheck() throws Exception { @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - if (out.getTransportVersion().before(TransportVersion.current())) { + if (out.getTransportVersion().before(transportVersion)) { throw new IllegalArgumentException( - "This request isn't serializable before transport version " + TransportVersion.current() + "This request isn't serializable before transport version " + transportVersion ); } } @@ -90,7 +92,7 @@ public void writeTo(StreamOutput out) throws IOException { assertThat(ex.getMessage(), containsString("not compatible with version")); assertThat(ex.getMessage(), containsString("and the 'search.check_ccs_compatibility' setting is enabled.")); assertEquals( - "This request isn't serializable before transport version " + TransportVersion.current(), + "This request isn't serializable before transport version " + transportVersion, ex.getCause().getMessage() ); } finally { diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesActionTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesActionTests.java index 39b52e4bda4a7..bfae7d7c3bf4f 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesActionTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.search.DummyQueryBuilder; import org.elasticsearch.search.SearchService; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -50,11 +51,12 @@ public void testCCSCompatibilityCheck() throws Exception { .build(); ActionFilters actionFilters = mock(ActionFilters.class); when(actionFilters.filters()).thenReturn(new ActionFilter[0]); + TransportVersion transportVersion = TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); try { TransportService transportService = MockTransportService.createNewService( Settings.EMPTY, VersionInformation.CURRENT, - TransportVersion.current(), + transportVersion, threadPool ); @@ -62,10 +64,8 @@ public void testCCSCompatibilityCheck() throws Exception { fieldCapsRequest.indexFilter(new DummyQueryBuilder() { @Override protected void doWriteTo(StreamOutput out) throws IOException { - if (out.getTransportVersion().before(TransportVersion.current())) { - throw new IllegalArgumentException( - "This query isn't serializable before transport version " + TransportVersion.current() - ); + if (out.getTransportVersion().before(transportVersion)) { + throw new IllegalArgumentException("This query isn't serializable before transport version " + transportVersion); } } }); @@ -100,10 +100,7 @@ protected void doWriteTo(StreamOutput out) throws IOException { containsString("[class org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest] is not compatible with version") ); assertThat(ex.getMessage(), containsString("and the 'search.check_ccs_compatibility' setting is enabled.")); - assertEquals( - "This query isn't serializable before transport version " + TransportVersion.current(), - ex.getCause().getMessage() - ); + assertEquals("This query isn't serializable before transport version " + transportVersion, ex.getCause().getMessage()); } finally { assertTrue(ESTestCase.terminate(threadPool)); } diff --git a/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java b/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java index 1c53e90d28c34..ca55483c1e7e0 100644 --- a/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java @@ -13,7 +13,6 @@ import org.apache.lucene.search.TotalHits; import org.apache.lucene.util.SetOnce; import org.elasticsearch.TransportVersion; -import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; import org.elasticsearch.action.OriginalIndices; @@ -78,6 +77,7 @@ import org.elasticsearch.search.vectors.KnnSearchBuilder; import org.elasticsearch.tasks.TaskId; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -1500,12 +1500,13 @@ public void testCCSCompatibilityCheck() throws Exception { .build(); ActionFilters actionFilters = mock(ActionFilters.class); when(actionFilters.filters()).thenReturn(new ActionFilter[0]); + TransportVersion transportVersion = TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); ThreadPool threadPool = new ThreadPool(settings); try { TransportService transportService = MockTransportService.createNewService( Settings.EMPTY, VersionInformation.CURRENT, - TransportVersion.current(), + transportVersion, threadPool ); @@ -1513,7 +1514,7 @@ public void testCCSCompatibilityCheck() throws Exception { searchRequest.source(new SearchSourceBuilder().query(new DummyQueryBuilder() { @Override protected void doWriteTo(StreamOutput out) throws IOException { - throw new IllegalArgumentException("Not serializable to " + Version.CURRENT); + throw new IllegalArgumentException("Not serializable to " + transportVersion); } })); NodeClient client = new NodeClient(settings, threadPool); @@ -1556,7 +1557,7 @@ public void onFailure(Exception ex) { containsString("[class org.elasticsearch.action.search.SearchRequest] is not compatible with version") ); assertThat(ex.getMessage(), containsString("and the 'search.check_ccs_compatibility' setting is enabled.")); - assertEquals("Not serializable to " + Version.CURRENT, ex.getCause().getMessage()); + assertEquals("Not serializable to " + transportVersion, ex.getCause().getMessage()); latch.countDown(); } }); diff --git a/test/framework/src/main/java/org/elasticsearch/test/TransportVersionUtils.java b/test/framework/src/main/java/org/elasticsearch/test/TransportVersionUtils.java index 8f4b6a1adfc12..93e43f2266a0e 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/TransportVersionUtils.java +++ b/test/framework/src/main/java/org/elasticsearch/test/TransportVersionUtils.java @@ -94,6 +94,10 @@ public static TransportVersion getPreviousVersion(TransportVersion version) { } public static TransportVersion getNextVersion(TransportVersion version) { + return getNextVersion(version, false); + } + + public static TransportVersion getNextVersion(TransportVersion version, boolean createIfNecessary) { int place = Collections.binarySearch(ALL_VERSIONS, version); if (place < 0) { // version does not exist - need the item at the index this version should be inserted @@ -104,7 +108,12 @@ public static TransportVersion getNextVersion(TransportVersion version) { } if (place < 0 || place >= ALL_VERSIONS.size()) { - throw new IllegalArgumentException("couldn't find any released versions after [" + version + "]"); + if (createIfNecessary) { + // create a new transport version one greater than specified + return new TransportVersion(version.id() + 1); + } else { + throw new IllegalArgumentException("couldn't find any released versions after [" + version + "]"); + } } return ALL_VERSIONS.get(place); } diff --git a/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java b/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java index 03b94c1f58b4b..b988e1ce5e980 100644 --- a/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java +++ b/x-pack/plugin/async-search/src/internalClusterTest/java/org/elasticsearch/xpack/search/AsyncSearchActionIT.java @@ -26,6 +26,7 @@ import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.query.ThrowingQueryBuilder; import org.elasticsearch.test.ESIntegTestCase.SuiteScopeTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.xpack.core.XPackPlugin; import org.elasticsearch.xpack.core.search.action.AsyncSearchResponse; import org.elasticsearch.xpack.core.search.action.AsyncStatusResponse; @@ -527,12 +528,11 @@ public void testMaxResponseSize() { updateClusterSettings(Settings.builder().put("search.max_async_search_response_size", (String) null)); } - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98557") public void testCCSCheckCompatibility() throws Exception { SubmitAsyncSearchRequest request = new SubmitAsyncSearchRequest(new SearchSourceBuilder().query(new DummyQueryBuilder() { @Override public TransportVersion getMinimalSupportedVersion() { - return TransportVersion.current(); + return TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); } }), indexName); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java index e913b879e8442..f2328d2837d03 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/TransportTermsEnumActionTests.java @@ -14,6 +14,7 @@ import org.elasticsearch.search.DummyQueryBuilder; import org.elasticsearch.search.SearchService; import org.elasticsearch.test.ESSingleNodeTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin; import org.elasticsearch.xpack.core.termsenum.action.TermsEnumAction; import org.elasticsearch.xpack.core.termsenum.action.TermsEnumRequest; @@ -66,13 +67,13 @@ public void onFailure(final Exception e) { /** * Test that triggering the CCS compatibility check with a query that shouldn't go to the minor before Version.CURRENT works */ - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98557") public void testCCSCheckCompatibility() throws Exception { TermsEnumRequest request = new TermsEnumRequest().field("field").timeout(TimeValue.timeValueSeconds(5)); + TransportVersion version = TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); request.indexFilter(new DummyQueryBuilder() { @Override public TransportVersion getMinimalSupportedVersion() { - return TransportVersion.current(); + return version; } }); ExecutionException ex = expectThrows(ExecutionException.class, () -> client().execute(TermsEnumAction.INSTANCE, request).get()); @@ -81,9 +82,7 @@ public TransportVersion getMinimalSupportedVersion() { assertThat( ex.getCause().getCause().getMessage(), containsString( - "was released first in version " - + TransportVersion.current() - + ", failed compatibility check trying to send it to node with version" + "was released first in version " + version + ", failed compatibility check trying to send it to node with version" ) ); } From ab022799f24c7f09b679f1a8d04d8b0a8bc41135 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 10:32:31 +0100 Subject: [PATCH 15/21] Apply spotless properly --- .../resolve/TransportResolveIndexActionTests.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java index 1768f66fea274..32554a65d11d3 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveIndexActionTests.java @@ -63,9 +63,7 @@ public void testCCSCompatibilityCheck() throws Exception { public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); if (out.getTransportVersion().before(transportVersion)) { - throw new IllegalArgumentException( - "This request isn't serializable before transport version " + transportVersion - ); + throw new IllegalArgumentException("This request isn't serializable before transport version " + transportVersion); } } }; @@ -91,10 +89,7 @@ public void writeTo(StreamOutput out) throws IOException { assertThat(ex.getMessage(), containsString("not compatible with version")); assertThat(ex.getMessage(), containsString("and the 'search.check_ccs_compatibility' setting is enabled.")); - assertEquals( - "This request isn't serializable before transport version " + transportVersion, - ex.getCause().getMessage() - ); + assertEquals("This request isn't serializable before transport version " + transportVersion, ex.getCause().getMessage()); } finally { assertTrue(ESTestCase.terminate(threadPool)); } From 57d6b9a8f3499fbdfeafa47914e26fceda02c2b2 Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Thu, 17 Aug 2023 10:44:01 +0100 Subject: [PATCH 16/21] [ML] Mute failing TransformConfigUpdateTests test (#98579) Relates #98577 --- .../core/transform/transforms/TransformConfigUpdateTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/transform/transforms/TransformConfigUpdateTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/transform/transforms/TransformConfigUpdateTests.java index 9f215f7d24625..1ea4394b6636f 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/transform/transforms/TransformConfigUpdateTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/transform/transforms/TransformConfigUpdateTests.java @@ -339,6 +339,7 @@ public void testApplyMetadata() { assertThat(updatedConfig.getMetadata(), equalTo(Map.of("bar", 789, "baz", 1000))); } + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98577") public void testApplyWithSyncChange() { TransformConfig batchConfig = new TransformConfig( "batch-transform", From 6b8cb583edc579b596fca347d8a98929a1d12ff2 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 11:37:50 +0100 Subject: [PATCH 17/21] Update allowed inferred versions to include 8.10 (#98578) Update some tests that could pass CURRENT to infer versions to real versions --- .../cluster/node/VersionInformation.java | 2 +- .../action/bulk/TransportBulkActionTests.java | 8 +++++++- .../action/bulk/TransportBulkActionTookTests.java | 8 +++++++- .../PublicationTransportHandlerTests.java | 14 ++++++++++++-- .../allocation/AllocationCommandsTests.java | 6 +++--- .../routing/allocation/FailedNodeRoutingTests.java | 7 ++++++- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/node/VersionInformation.java b/server/src/main/java/org/elasticsearch/cluster/node/VersionInformation.java index 84b5946c8e19f..631280663fcb0 100644 --- a/server/src/main/java/org/elasticsearch/cluster/node/VersionInformation.java +++ b/server/src/main/java/org/elasticsearch/cluster/node/VersionInformation.java @@ -32,7 +32,7 @@ public static VersionInformation inferVersions(Version nodeVersion) { return null; } else if (nodeVersion.equals(Version.CURRENT)) { return CURRENT; - } else if (nodeVersion.before(Version.V_8_10_0)) { + } else if (nodeVersion.onOrBefore(Version.V_8_10_0)) { return new VersionInformation( nodeVersion, IndexVersion.fromId(nodeVersion.minimumIndexCompatibilityVersion().id), diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java index d92387dc818e2..03229e14d724a 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.IndexingPressure; import org.elasticsearch.index.VersionType; import org.elasticsearch.indices.EmptySystemIndices; @@ -40,6 +41,7 @@ import org.elasticsearch.indices.SystemIndices; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.VersionUtils; +import org.elasticsearch.test.index.IndexVersionUtils; import org.elasticsearch.test.transport.CapturingTransport; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -107,7 +109,11 @@ public void setUp() throws Exception { super.setUp(); threadPool = new TestThreadPool(getClass().getName()); DiscoveryNode discoveryNode = DiscoveryNodeUtils.builder("node") - .version(VersionUtils.randomCompatibleVersion(random(), Version.CURRENT)) + .version( + VersionUtils.randomCompatibleVersion(random(), Version.CURRENT), + IndexVersion.MINIMUM_COMPATIBLE, + IndexVersionUtils.randomCompatibleVersion(random()) + ) .build(); clusterService = createClusterService(threadPool, discoveryNode); CapturingTransport capturingTransport = new CapturingTransport(); diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTookTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTookTests.java index d13fe14416631..7e9556be18f6d 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTookTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTookTests.java @@ -29,11 +29,13 @@ import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.IndexingPressure; import org.elasticsearch.indices.EmptySystemIndices; import org.elasticsearch.tasks.Task; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.VersionUtils; +import org.elasticsearch.test.index.IndexVersionUtils; import org.elasticsearch.test.transport.CapturingTransport; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -77,7 +79,11 @@ public static void afterClass() { public void setUp() throws Exception { super.setUp(); DiscoveryNode discoveryNode = DiscoveryNodeUtils.builder("node") - .version(VersionUtils.randomCompatibleVersion(random(), Version.CURRENT)) + .version( + VersionUtils.randomCompatibleVersion(random(), Version.CURRENT), + IndexVersion.MINIMUM_COMPATIBLE, + IndexVersionUtils.randomCompatibleVersion(random()) + ) .build(); clusterService = createClusterService(threadPool, discoveryNode); } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java index 98af9283d7863..7e11d33a2a396 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java @@ -36,11 +36,13 @@ import org.elasticsearch.common.util.concurrent.DeterministicTaskQueue; import org.elasticsearch.core.IOUtils; import org.elasticsearch.core.Nullable; +import org.elasticsearch.index.IndexVersion; import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.TaskId; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.test.VersionUtils; +import org.elasticsearch.test.index.IndexVersionUtils; import org.elasticsearch.test.transport.MockTransport; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -224,7 +226,11 @@ public RecyclerBytesStreamOutput newNetworkBytesStream() { final List allNodes = new ArrayList<>(); while (allNodes.size() < 10) { var node = DiscoveryNodeUtils.builder("node-" + allNodes.size()) - .version(VersionUtils.randomCompatibleVersion(random(), Version.CURRENT)) + .version( + VersionUtils.randomCompatibleVersion(random(), Version.CURRENT), + IndexVersion.MINIMUM_COMPATIBLE, + IndexVersionUtils.randomCompatibleVersion(random()) + ) .build(); allNodes.add(node); nodeTransports.put( @@ -355,7 +361,11 @@ public void testIncludesLastCommittedFieldsInDiffSerialization() { final var localNode = DiscoveryNodeUtils.create("localNode"); final var otherNode = DiscoveryNodeUtils.builder("otherNode") - .version(VersionUtils.randomCompatibleVersion(random(), Version.CURRENT)) + .version( + VersionUtils.randomCompatibleVersion(random(), Version.CURRENT), + IndexVersion.MINIMUM_COMPATIBLE, + IndexVersionUtils.randomCompatibleVersion(random()) + ) .build(); for (final var discoveryNode : List.of(localNode, otherNode)) { final var transport = new MockTransport() { diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/AllocationCommandsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/AllocationCommandsTests.java index b51889170b904..958532011b281 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/AllocationCommandsTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/AllocationCommandsTests.java @@ -713,9 +713,9 @@ public void testCanceledShardIsInitializedRespectingAllocationDeciders() { ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT) .nodes( DiscoveryNodes.builder() - .add(newNode("node-0", Version.V_8_10_0)) - .add(newNode("node-1", Version.V_8_9_0)) - .add(newNode("node-2", Version.V_8_9_0)) + .add(newNode("node-0", Version.V_8_10_0, IndexVersion.V_8_10_0)) + .add(newNode("node-1", Version.V_8_9_0, IndexVersion.V_8_9_0)) + .add(newNode("node-2", Version.V_8_9_0, IndexVersion.V_8_9_0)) ) .metadata(Metadata.builder().put(indexMetadata, false)) .routingTable(RoutingTable.builder().add(IndexRoutingTable.builder(shardId.getIndex()).addShard(primary).addShard(replica))) diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java index f8b61f3dbd1ec..1d796c931270b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java @@ -36,6 +36,7 @@ import org.elasticsearch.index.IndexVersion; import org.elasticsearch.indices.cluster.ClusterStateChanges; import org.elasticsearch.test.VersionUtils; +import org.elasticsearch.test.index.IndexVersionUtils; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -224,7 +225,11 @@ protected DiscoveryNode createNode(DiscoveryNodeRole... mustHaveRoles) { return DiscoveryNodeUtils.builder(id) .name(id) .roles(roles) - .version(VersionUtils.randomCompatibleVersion(random(), Version.CURRENT)) + .version( + VersionUtils.randomCompatibleVersion(random(), Version.CURRENT), + IndexVersion.MINIMUM_COMPATIBLE, + IndexVersionUtils.randomCompatibleVersion(random()) + ) .build(); } From 9538208fb75f8b036905f228bd9bd6e6cb26c8f9 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 11:38:31 +0100 Subject: [PATCH 18/21] Fix shard-stores doc test (#98581) The replacement wasn't actually doing anything due to different JSON types --- docs/reference/indices/shard-stores.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/indices/shard-stores.asciidoc b/docs/reference/indices/shard-stores.asciidoc index 79394fccd046c..562c146949718 100644 --- a/docs/reference/indices/shard-stores.asciidoc +++ b/docs/reference/indices/shard-stores.asciidoc @@ -192,8 +192,8 @@ The API returns the following response: // TESTRESPONSE[s/"attributes": \{[^}]*\}/"attributes": $body.$_path/] // TESTRESPONSE[s/"roles": \[[^]]*\]/"roles": $body.$_path/] // TESTRESPONSE[s/"8.10.0"/\$node_version/] -// TESTRESPONSE[s/"7000099"/"\d+"/] -// TESTRESPONSE[s/"8100099"/"\d+"/] +// TESTRESPONSE[s/"min_index_version": 7000099/"min_index_version": $body.$_path/] +// TESTRESPONSE[s/"max_index_version": 8100099/"max_index_version": $body.$_path/] From 264abd30417052ac7e5222a0eb2eba58b0dcae50 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 12:48:07 +0100 Subject: [PATCH 19/21] Fix another CCS compatibility test (#98585) --- .../java/org/elasticsearch/search/msearch/MultiSearchIT.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/msearch/MultiSearchIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/msearch/MultiSearchIT.java index f849496c2df16..cc3d21efd71bc 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/msearch/MultiSearchIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/msearch/MultiSearchIT.java @@ -16,6 +16,7 @@ import org.elasticsearch.search.DummyQueryBuilder; import org.elasticsearch.search.SearchService; import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.TransportVersionUtils; import org.elasticsearch.xcontent.XContentType; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFirstHit; @@ -86,6 +87,7 @@ public void testSimpleMultiSearchMoreRequests() { * Test that triggering the CCS compatibility check with a query that shouldn't go to the minor before Version.CURRENT works */ public void testCCSCheckCompatibility() throws Exception { + TransportVersion transportVersion = TransportVersionUtils.getNextVersion(TransportVersion.MINIMUM_CCS_VERSION, true); createIndex("test"); ensureGreen(); client().prepareIndex("test").setId("1").setSource("field", "xxx").get(); @@ -97,7 +99,7 @@ public void testCCSCheckCompatibility() throws Exception { .add(client().prepareSearch("test").setQuery(new DummyQueryBuilder() { @Override public TransportVersion getMinimalSupportedVersion() { - return TransportVersion.current(); + return transportVersion; } })) .get(); From 0754bd89431793a916a4e6be7624e513770fc57e Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Thu, 17 Aug 2023 13:35:52 +0100 Subject: [PATCH 20/21] Unmute FeatureUpgradeIT test (#98576) Test was fixed by #98574 --- .../test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java index 7c5999a981b69..74ba81e9555e2 100644 --- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java +++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/FeatureUpgradeIT.java @@ -24,7 +24,6 @@ public class FeatureUpgradeIT extends AbstractRollingTestCase { @SuppressWarnings("unchecked") - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98562") public void testGetFeatureUpgradeStatus() throws Exception { final String systemIndexWarning = "this request accesses system indices: [.tasks], but in a future major version, direct " From af071ccc314a0975a9b6e1b6ce7d2a9f92d75a09 Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Thu, 17 Aug 2023 14:06:05 +0100 Subject: [PATCH 21/21] [M]] Fix failing JobNodeSelectorTests (#98541) Tests have started failing in 8.11 as they are missing an appropriate value for the ML_CONFIG_VERSION_NODE_ATTR node attribute --- .../xpack/ml/job/JobNodeSelectorTests.java | 72 +++++++++++++------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java index 32a684097d601..19546b37c00cd 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/JobNodeSelectorTests.java @@ -6,7 +6,6 @@ */ package org.elasticsearch.xpack.ml.job; -import org.apache.lucene.tests.util.LuceneTestCase; import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; @@ -59,7 +58,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/98552") public class JobNodeSelectorTests extends ESTestCase { // To simplify the logic in this class all jobs have the same memory requirement @@ -116,7 +114,9 @@ public void testSelectLeastLoadedMlNodeForAnomalyDetectorJob_maxCapacityCountLim MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, maxRunningJobsPerNode); @@ -162,7 +162,9 @@ public void testSelectLeastLoadedMlNodeForDataFrameAnalyticsJob_maxCapacityCount MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, maxRunningJobsPerNode); @@ -214,7 +216,9 @@ public void testSelectLeastLoadedMlNodeForAnomalyDetectorJob_maxCapacityMemoryLi MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, currentlyRunningJobsPerNode); @@ -268,7 +272,9 @@ public void testSelectLeastLoadedMlNodeForDataFrameAnalyticsJob_givenTaskHasNull MachineLearning.MACHINE_MEMORY_NODE_ATTR, String.valueOf(ByteSizeValue.ofGb(1).getBytes()), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - String.valueOf(ByteSizeValue.ofMb(400).getBytes()) + String.valueOf(ByteSizeValue.ofMb(400).getBytes()), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, 1, JobState.OPENED, null); @@ -305,7 +311,9 @@ public void testSelectLeastLoadedMlNodeForAnomalyDetectorJob_firstJobTooBigMemor MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, 0); @@ -362,7 +370,9 @@ public void testSelectLeastLoadedMlNodeForDataFrameAnalyticsJob_maxCapacityMemor MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, currentlyRunningJobsPerNode); @@ -418,7 +428,9 @@ public void testSelectLeastLoadedMlNodeForDataFrameAnalyticsJob_firstJobTooBigMe MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, 0); @@ -512,7 +524,9 @@ public void testSelectLeastLoadedMlNode_maxConcurrentOpeningJobs() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -644,7 +658,9 @@ public void testSelectLeastLoadedMlNode_concurrentOpeningJobsAndStaleFailedJob() MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -739,7 +755,9 @@ public void testSelectLeastLoadedMlNode_noCompatibleJobTypeNodes() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -797,7 +815,9 @@ public void testSelectLeastLoadedMlNode_reasonsAreInDeterministicOrder() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -935,7 +955,9 @@ public void testSelectLeastLoadedMlNode_jobWithRules() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -989,7 +1011,9 @@ public void testSelectMlNodeOnlyOutOfCandidates() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, "1000000000", MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - "400000000" + "400000000", + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); DiscoveryNodes nodes = DiscoveryNodes.builder() .add( @@ -1188,7 +1212,9 @@ public void testMaximumPossibleNodeMemoryTooSmall() { MachineLearning.MACHINE_MEMORY_NODE_ATTR, Long.toString(machineMemory), MachineLearning.MAX_JVM_SIZE_NODE_ATTR, - Long.toString(machineMemory / 2) + Long.toString(machineMemory / 2), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ); ClusterState.Builder cs = fillNodesWithRunningJobs(nodeAttr, numNodes, maxRunningJobsPerNode); @@ -1229,7 +1255,7 @@ public void testPerceivedCapacityAndMaxFreeMemory() { "not_ml_node_name", "_node_id", new TransportAddress(InetAddress.getLoopbackAddress(), 9300), - Collections.emptyMap(), + Map.of(MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, MlConfigVersion.CURRENT.toString()), ROLES_WITHOUT_ML ) ) @@ -1242,7 +1268,9 @@ public void testPerceivedCapacityAndMaxFreeMemory() { MachineLearning.MAX_JVM_SIZE_NODE_ATTR, "10", MachineLearning.MACHINE_MEMORY_NODE_ATTR, - Long.toString(ByteSizeValue.ofGb(30).getBytes()) + Long.toString(ByteSizeValue.ofGb(30).getBytes()), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ), ROLES_WITH_ML ) @@ -1256,7 +1284,9 @@ public void testPerceivedCapacityAndMaxFreeMemory() { MachineLearning.MAX_JVM_SIZE_NODE_ATTR, "10", MachineLearning.MACHINE_MEMORY_NODE_ATTR, - Long.toString(ByteSizeValue.ofGb(30).getBytes()) + Long.toString(ByteSizeValue.ofGb(30).getBytes()), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ), ROLES_WITH_ML ) @@ -1270,7 +1300,9 @@ public void testPerceivedCapacityAndMaxFreeMemory() { MachineLearning.MAX_JVM_SIZE_NODE_ATTR, "10", MachineLearning.MACHINE_MEMORY_NODE_ATTR, - Long.toString(ByteSizeValue.ofGb(10).getBytes()) + Long.toString(ByteSizeValue.ofGb(10).getBytes()), + MlConfigVersion.ML_CONFIG_VERSION_NODE_ATTR, + MlConfigVersion.CURRENT.toString() ), ROLES_WITH_ML )