From 8e9e9bc6c886e35277c5d6e315f45405673afb86 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 11 Jun 2024 11:53:18 +0200 Subject: [PATCH 01/18] Relaxed resulting docs checks (#109560) --- .../180_update_dense_vector_type.yml | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/180_update_dense_vector_type.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/180_update_dense_vector_type.yml index 0780b789e92a1..3502a5e643087 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/180_update_dense_vector_type.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/180_update_dense_vector_type.yml @@ -2,6 +2,9 @@ setup: - requires: cluster_features: "gte_v8.15.0" reason: 'updatable dense vector field types was added in 8.15' + - skip: + reason: "contains is a newly added assertion" + features: contains --- "Test create and update dense vector mapping with per-doc indexing and flush": - do: @@ -110,9 +113,9 @@ setup: - match: { hits.total.value: 10 } - length: {hits.hits: 3} - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "3" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "3" } } - do: indices.put_mapping: @@ -216,9 +219,9 @@ setup: - match: { hits.total.value: 20 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "11" } - - match: { hits.hits.2._id: "2" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "11" } } + - contains: { hits.hits: { _id: "2" } } - do: indices.put_mapping: @@ -323,10 +326,10 @@ setup: - match: { hits.total.value: 30 } - length: { hits.hits: 4 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "11" } - - match: { hits.hits.2._id: "2" } - - match: { hits.hits.3._id: "21" } + - contains: {hits.hits: {_id: "1"}} + - contains: {hits.hits: {_id: "11"}} + - contains: {hits.hits: {_id: "2"}} + - contains: {hits.hits: {_id: "21"}} - do: indices.put_mapping: @@ -431,12 +434,11 @@ setup: - match: { hits.total.value: 40 } - length: { hits.hits: 5 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "11" } - - match: { hits.hits.2._id: "31" } - - match: { hits.hits.3._id: "2" } - - match: { hits.hits.4._id: "21" } - + - contains: {hits.hits: {_id: "1"}} + - contains: {hits.hits: {_id: "11"}} + - contains: {hits.hits: {_id: "2"}} + - contains: {hits.hits: {_id: "21"}} + - contains: {hits.hits: {_id: "31"}} --- "Test create and update dense vector mapping with bulk indexing": @@ -501,9 +503,9 @@ setup: - match: { hits.total.value: 10 } - length: {hits.hits: 3} - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "3" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "3" } } - do: indices.put_mapping: @@ -561,9 +563,9 @@ setup: - match: { hits.total.value: 20 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "11" } } - do: indices.put_mapping: @@ -622,10 +624,10 @@ setup: - match: { hits.total.value: 30 } - length: { hits.hits: 4 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "21" } - - match: { hits.hits.3._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "11" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "21" } } - do: indices.put_mapping: @@ -684,11 +686,11 @@ setup: - match: { hits.total.value: 40 } - length: { hits.hits: 5 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "21" } - - match: { hits.hits.3._id: "31" } - - match: { hits.hits.4._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "11" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "21" } } + - contains: { hits.hits: { _id: "31" } } --- "Index, update and merge": @@ -753,9 +755,9 @@ setup: - match: { hits.total.value: 10 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "3" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "3" } } - do: indices.put_mapping: @@ -793,9 +795,9 @@ setup: - match: { hits.total.value: 10 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "3" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "3" } } - do: bulk: @@ -835,9 +837,9 @@ setup: - match: { hits.total.value: 20 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "11" } } - do: indices.put_mapping: @@ -871,9 +873,9 @@ setup: - match: { hits.total.value: 20 } - length: { hits.hits: 3 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "11" } } - do: bulk: @@ -913,10 +915,10 @@ setup: - match: { hits.total.value: 30 } - length: { hits.hits: 4 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "21" } - - match: { hits.hits.3._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "11" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "21" } } - do: indices.forcemerge: @@ -936,10 +938,10 @@ setup: - match: { hits.total.value: 30 } - length: { hits.hits: 4 } - - match: { hits.hits.0._id: "1" } - - match: { hits.hits.1._id: "2" } - - match: { hits.hits.2._id: "21" } - - match: { hits.hits.3._id: "11" } + - contains: { hits.hits: { _id: "1" } } + - contains: { hits.hits: { _id: "11" } } + - contains: { hits.hits: { _id: "2" } } + - contains: { hits.hits: { _id: "21" } } --- From c471b01f9e6bf8357c4260fabcd8d94995b1a426 Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Tue, 11 Jun 2024 11:40:10 +0100 Subject: [PATCH 02/18] Add permission to secure access to certain config files specified by settings (#108895) --- docs/changelog/108895.yaml | 5 + ...=> SecuredConfigFileAccessPermission.java} | 11 +- ...uredConfigFileSettingAccessPermission.java | 26 ++++ .../elasticsearch/bootstrap/PolicyUtil.java | 6 +- .../org/elasticsearch/bootstrap/Security.java | 111 +++++++++++++----- 5 files changed, 123 insertions(+), 36 deletions(-) create mode 100644 docs/changelog/108895.yaml rename server/src/main/java/org/elasticsearch/{SecuredFileAccessPermission.java => SecuredConfigFileAccessPermission.java} (53%) create mode 100644 server/src/main/java/org/elasticsearch/SecuredConfigFileSettingAccessPermission.java diff --git a/docs/changelog/108895.yaml b/docs/changelog/108895.yaml new file mode 100644 index 0000000000000..15293896b20c5 --- /dev/null +++ b/docs/changelog/108895.yaml @@ -0,0 +1,5 @@ +pr: 108895 +summary: Add permission to secure access to certain config files specified by settings +area: "Security" +type: bug +issues: [] diff --git a/server/src/main/java/org/elasticsearch/SecuredFileAccessPermission.java b/server/src/main/java/org/elasticsearch/SecuredConfigFileAccessPermission.java similarity index 53% rename from server/src/main/java/org/elasticsearch/SecuredFileAccessPermission.java rename to server/src/main/java/org/elasticsearch/SecuredConfigFileAccessPermission.java index 3d24a9bc5ddb3..d6372b5ef9885 100644 --- a/server/src/main/java/org/elasticsearch/SecuredFileAccessPermission.java +++ b/server/src/main/java/org/elasticsearch/SecuredConfigFileAccessPermission.java @@ -13,13 +13,14 @@ /** * A permission granted to ensure secured access to a file in the config directory. *

- * By granting this permission, all code that does not have the same permission on the same file - * will be denied all read/write access to that file. - * Note that you also need to wrap any access to the secured files in an {@code AccessController.doPrivileged()} block + * By granting this permission with a file relative to the config directory, + * the file is secured from general access by Elasticsearch and other Elasticsearch plugins. + * All code that does not have a secured permission on the same file will be denied all read/write access to that file. + * Note that you also need to wrap any access to secured files in an {@code AccessController.doPrivileged()} block * as Elasticsearch itself is denied access to files secured by plugins. */ -public class SecuredFileAccessPermission extends BasicPermission { - public SecuredFileAccessPermission(String path) { +public class SecuredConfigFileAccessPermission extends BasicPermission { + public SecuredConfigFileAccessPermission(String path) { super(path, ""); } } diff --git a/server/src/main/java/org/elasticsearch/SecuredConfigFileSettingAccessPermission.java b/server/src/main/java/org/elasticsearch/SecuredConfigFileSettingAccessPermission.java new file mode 100644 index 0000000000000..fdea47d449a15 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/SecuredConfigFileSettingAccessPermission.java @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch; + +import java.security.BasicPermission; + +/** + * A permission granted to ensure secured access to a file specified by a setting in the config directory. + *

+ * By granting this permission with a setting key (wildcards are supported), + * the files pointed to by the settings are secured from general access by Elasticsearch and other Elasticsearch plugins. + * All code that does not have a secured permission on the same file will be denied all read/write access to that file. + * Note that you also need to wrap any access to secured files in an {@code AccessController.doPrivileged()} block + * as Elasticsearch itself is denied access to files secured by plugins. + */ +public class SecuredConfigFileSettingAccessPermission extends BasicPermission { + public SecuredConfigFileSettingAccessPermission(String setting) { + super(setting, ""); + } +} diff --git a/server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java b/server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java index 3279bc5b1bfdf..b9574f1a29ae8 100644 --- a/server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java +++ b/server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java @@ -8,7 +8,8 @@ package org.elasticsearch.bootstrap; -import org.elasticsearch.SecuredFileAccessPermission; +import org.elasticsearch.SecuredConfigFileAccessPermission; +import org.elasticsearch.SecuredConfigFileSettingAccessPermission; import org.elasticsearch.core.IOUtils; import org.elasticsearch.core.PathUtils; import org.elasticsearch.core.SuppressForbidden; @@ -169,7 +170,8 @@ public boolean test(Permission permission) { entry(PrivateCredentialPermission.class, ALLOW_ALL_NAMES), entry(SQLPermission.class, List.of("callAbort", "setNetworkTimeout")), entry(ClassPermission.class, ALLOW_ALL_NAMES), - entry(SecuredFileAccessPermission.class, ALLOW_ALL_NAMES) + entry(SecuredConfigFileAccessPermission.class, ALLOW_ALL_NAMES), + entry(SecuredConfigFileSettingAccessPermission.class, ALLOW_ALL_NAMES) ).collect(Collectors.toMap(e -> e.getKey().getCanonicalName(), Map.Entry::getValue)); PermissionCollection pluginPermissionCollection = new Permissions(); namedPermissions.forEach(pluginPermissionCollection::add); diff --git a/server/src/main/java/org/elasticsearch/bootstrap/Security.java b/server/src/main/java/org/elasticsearch/bootstrap/Security.java index e24e13dfff372..12edf344c72a2 100644 --- a/server/src/main/java/org/elasticsearch/bootstrap/Security.java +++ b/server/src/main/java/org/elasticsearch/bootstrap/Security.java @@ -9,13 +9,16 @@ package org.elasticsearch.bootstrap; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.SecuredFileAccessPermission; +import org.elasticsearch.SecuredConfigFileAccessPermission; +import org.elasticsearch.SecuredConfigFileSettingAccessPermission; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.PathUtils; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.env.Environment; import org.elasticsearch.http.HttpTransportSettings; import org.elasticsearch.jdk.JarHell; +import org.elasticsearch.logging.LogManager; +import org.elasticsearch.logging.Logger; import org.elasticsearch.plugins.PluginsUtils; import org.elasticsearch.secure_sm.SecureSM; import org.elasticsearch.transport.TcpTransport; @@ -46,7 +49,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Stream; +import java.util.regex.Pattern; import static java.lang.invoke.MethodType.methodType; import static org.elasticsearch.bootstrap.ESPolicy.POLICY_RESOURCE; @@ -104,6 +107,8 @@ */ final class Security { + private static Logger logger; // not init'd until configure call below + static { prepopulateSecurityCaller(); } @@ -122,6 +127,8 @@ static void setSecurityManager(@SuppressWarnings("removal") SecurityManager sm) * @param filterBadDefaults true if we should filter out bad java defaults in the system policy. */ static void configure(Environment environment, boolean filterBadDefaults, Path pidFile) throws IOException { + logger = LogManager.getLogger(Security.class); + // enable security policy: union of template and environment-based paths, and possibly plugin permissions Map codebases = PolicyUtil.getCodebaseJarMap(JarHell.parseModulesAndClassPath()); Policy mainPolicy = PolicyUtil.readPolicy(ESPolicy.class.getResource(POLICY_RESOURCE), codebases); @@ -133,7 +140,7 @@ static void configure(Environment environment, boolean filterBadDefaults, Path p pluginPolicies, filterBadDefaults, createRecursiveDataPathPermission(environment), - readSecuredFiles(environment, mainPolicy, codebases.values(), pluginPolicies) + readSecuredConfigFiles(environment, mainPolicy, codebases.values(), pluginPolicies) ) ); @@ -196,55 +203,101 @@ private static List createRecursiveDataPathPermission(Environmen return toFilePermissions(policy); } - private static Map> readSecuredFiles( + private static Map> readSecuredConfigFiles( Environment environment, Policy template, Collection mainCodebases, Map pluginPolicies ) throws IOException { - Map> securedFiles = new HashMap<>(); + Map> securedConfigFiles = new HashMap<>(); + Map> securedSettingKeys = new HashMap<>(); for (URL url : mainCodebases) { - PolicyUtil.getPolicyPermissions(url, template, environment.tmpFile()) - .stream() - .flatMap(Security::extractSecuredFileName) - .map(environment.configFile()::resolve) - .forEach(f -> securedFiles.computeIfAbsent(f.toString(), k -> new HashSet<>()).add(url)); + for (Permission p : PolicyUtil.getPolicyPermissions(url, template, environment.tmpFile())) { + readSecuredConfigFilePermissions(environment, url, p, securedConfigFiles, securedSettingKeys); + } } for (var pp : pluginPolicies.entrySet()) { - PolicyUtil.getPolicyPermissions(pp.getKey(), pp.getValue(), environment.tmpFile()) - .stream() - .flatMap(Security::extractSecuredFileName) - .map(environment.configFile()::resolve) - .forEach(f -> securedFiles.computeIfAbsent(f.toString(), k -> new HashSet<>()).add(pp.getKey())); + for (Permission p : PolicyUtil.getPolicyPermissions(pp.getKey(), pp.getValue(), environment.tmpFile())) { + readSecuredConfigFilePermissions(environment, pp.getKey(), p, securedConfigFiles, securedSettingKeys); + } + } + + // compile a Pattern for each setting key we'll be looking for + // the key could include a * wildcard + List>> settingPatterns = securedSettingKeys.entrySet() + .stream() + .map(e -> Map.entry(Pattern.compile(e.getKey()), e.getValue())) + .toList(); + + for (String setting : environment.settings().keySet()) { + for (Map.Entry> ps : settingPatterns) { + if (ps.getKey().matcher(setting).matches()) { + // add the setting value to the secured files for these codebase URLs + Path file = environment.configFile().resolve(environment.settings().get(setting)); + if (file.startsWith(environment.configFile()) == false) { + throw new IllegalStateException(ps.getValue() + " tried to grant access to file outside config directory " + file); + } + if (logger.isDebugEnabled()) { + ps.getValue() + .forEach( + url -> logger.debug("Jar {} securing access to config file {} through setting {}", url, file, setting) + ); + } + securedConfigFiles.computeIfAbsent(file.toString(), k -> new HashSet<>()).addAll(ps.getValue()); + } + } } // always add some config files as exclusive files that no one can access // there's no reason for anyone to read these once the security manager is initialized // so if something has tried to grant itself access, crash out with an error - addSpeciallySecuredFile(securedFiles, environment.configFile().resolve("elasticsearch.yml").toString()); - addSpeciallySecuredFile(securedFiles, environment.configFile().resolve("jvm.options").toString()); - addSpeciallySecuredFile(securedFiles, environment.configFile().resolve("jvm.options.d/-").toString()); + addSpeciallySecuredConfigFile(securedConfigFiles, environment.configFile().resolve("elasticsearch.yml").toString()); + addSpeciallySecuredConfigFile(securedConfigFiles, environment.configFile().resolve("jvm.options").toString()); + addSpeciallySecuredConfigFile(securedConfigFiles, environment.configFile().resolve("jvm.options.d/-").toString()); - return Collections.unmodifiableMap(securedFiles); + return Collections.unmodifiableMap(securedConfigFiles); } - private static void addSpeciallySecuredFile(Map> securedFiles, String path) { - Set attemptedToGrant = securedFiles.put(path, Set.of()); - if (attemptedToGrant != null) { - throw new IllegalStateException(attemptedToGrant + " tried to grant access to special config file " + path); + private static void readSecuredConfigFilePermissions( + Environment environment, + URL url, + Permission p, + Map> securedFiles, + Map> securedSettingKeys + ) { + String securedFileName = extractSecuredName(p, SecuredConfigFileAccessPermission.class); + if (securedFileName != null) { + Path securedFile = environment.configFile().resolve(securedFileName); + if (securedFile.startsWith(environment.configFile()) == false) { + throw new IllegalStateException("[" + url + "] tried to grant access to file outside config directory " + securedFile); + } + logger.debug("Jar {} securing access to config file {}", url, securedFile); + securedFiles.computeIfAbsent(securedFile.toString(), k -> new HashSet<>()).add(url); + } + + String securedKey = extractSecuredName(p, SecuredConfigFileSettingAccessPermission.class); + if (securedKey != null) { + securedSettingKeys.computeIfAbsent(securedKey, k -> new HashSet<>()).add(url); } } - private static Stream extractSecuredFileName(Permission p) { - if (p instanceof SecuredFileAccessPermission) { - return Stream.of(p.getName()); + private static String extractSecuredName(Permission p, Class permissionType) { + if (permissionType.isInstance(p)) { + return p.getName(); + } else if (p instanceof UnresolvedPermission up && up.getUnresolvedType().equals(permissionType.getCanonicalName())) { + return up.getUnresolvedName(); + } else { + return null; } - if (p instanceof UnresolvedPermission up && up.getUnresolvedType().equals(SecuredFileAccessPermission.class.getCanonicalName())) { - return Stream.of(up.getUnresolvedName()); + } + + private static void addSpeciallySecuredConfigFile(Map> securedFiles, String path) { + Set attemptedToGrant = securedFiles.put(path, Set.of()); + if (attemptedToGrant != null) { + throw new IllegalStateException(attemptedToGrant + " tried to grant access to special config file " + path); } - return Stream.empty(); } /** Adds access to classpath jars/classes for jar hell scan, etc */ From 9647f6bd12f08b947203abcceefaeb15dc7d12cf Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Tue, 11 Jun 2024 12:52:20 +0200 Subject: [PATCH 03/18] Don't set number of shards to 0 for system indices that use auto-expand replicas (#108994) Many of our system indices that rely on auto_expand_replicas get created providing a manual number of replicas. Such number will be immediately overridden by the auto expand replicas functionality according to the number of data nodes available. While this causes no harm, it seems misleading and unnecessary, a potential misuse that we can avoid for indices that we create ourselves. Ideally we'd even prevent this from happening by rejecting such index creation requests, but that would be a breaking change that we'd prefer not to make at this time. --- .../java/org/elasticsearch/ingest/geoip/IngestGeoIpPlugin.java | 1 - .../java/org/elasticsearch/system/indices/SystemIndicesQA.java | 2 -- .../elasticsearch/synonyms/SynonymsManagementAPIService.java | 1 - .../elasticsearch/xpack/core/async/AsyncTaskIndexService.java | 1 - .../xpack/application/rules/QueryRulesIndexService.java | 1 - .../application/search/SearchApplicationIndexService.java | 1 - .../xpack/security/support/SecuritySystemIndices.java | 3 --- .../src/main/java/org/elasticsearch/xpack/watcher/Watcher.java | 1 - 8 files changed, 11 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 e5756652a9842..9d0f9848d97b6 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 @@ -188,7 +188,6 @@ public Collection getSystemIndexDescriptors(Settings sett .setSettings( Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .build() ) 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 9fc256e79873e..1d69ae5c1ee4a 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 @@ -72,7 +72,6 @@ public Collection getSystemIndexDescriptors(Settings sett .setSettings( Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .build() ) @@ -95,7 +94,6 @@ public Collection getSystemIndexDescriptors(Settings sett .setSettings( Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .build() ) diff --git a/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java b/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java index 9409aef96d8be..2cd35fd6889bd 100644 --- a/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java +++ b/server/src/main/java/org/elasticsearch/synonyms/SynonymsManagementAPIService.java @@ -483,7 +483,6 @@ private static String internalSynonymRuleId(String synonymsSetId, String synonym static Settings settings() { return Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-all") .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), SYNONYMS_INDEX_FORMAT) .build(); 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 2d92ded3b5454..e44af60a45e08 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 @@ -99,7 +99,6 @@ static Settings settings() { return Settings.builder() .put("index.codec", "best_compression") .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .build(); } 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 adcd5da988b82..86192d8070cc1 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 @@ -102,7 +102,6 @@ public static SystemIndexDescriptor getSystemIndexDescriptor() { private static Settings getIndexSettings() { return Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .put(IndexMetadata.SETTING_PRIORITY, 100) .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), QueryRulesIndexMappingVersion.latest().id) 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 0ccef9acba088..9e8a8f750b764 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 @@ -139,7 +139,6 @@ public static SystemIndexDescriptor getSystemIndexDescriptor() { private static Settings getIndexSettings() { return Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .put(IndexMetadata.SETTING_PRIORITY, 100) .put("index.refresh_interval", "1s") 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 75937bf3e2c18..4c5ce703f48ad 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 @@ -152,7 +152,6 @@ private SystemIndexDescriptor getSecurityMainIndexDescriptor() { private static Settings getMainIndexSettings() { return Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .put(IndexMetadata.SETTING_PRIORITY, 1000) .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), INTERNAL_MAIN_INDEX_FORMAT) @@ -667,7 +666,6 @@ private static SystemIndexDescriptor getSecurityTokenIndexDescriptor() { private static Settings getTokenIndexSettings() { return Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .put(IndexMetadata.SETTING_PRIORITY, 1000) .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), INTERNAL_TOKENS_INDEX_FORMAT) @@ -868,7 +866,6 @@ private SystemIndexDescriptor getSecurityProfileIndexDescriptor(Settings setting private static Settings getProfileIndexSettings(Settings settings) { final Settings.Builder settingsBuilder = Settings.builder() .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1") .put(IndexMetadata.SETTING_PRIORITY, 1000) .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), INTERNAL_PROFILE_INDEX_FORMAT) 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 f8f910c38c080..2d71aef08ea13 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 @@ -874,7 +874,6 @@ public String getFeatureDescription() { private static Settings getWatchesIndexSettings() { return Settings.builder() .put("index.number_of_shards", 1) - .put("index.number_of_replicas", 0) .put("index.auto_expand_replicas", "0-1") .put(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), 6) .put(IndexMetadata.SETTING_PRIORITY, 800) From 90ab2558b03f59c38b8223c2b881f97da7cd4394 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 11 Jun 2024 08:07:40 -0400 Subject: [PATCH 04/18] Adjusting bwc version after backport of #109423 (#109469) Co-authored-by: Elastic Machine --- .../170_knn_search_hex_encoded_byte_vectors.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/170_knn_search_hex_encoded_byte_vectors.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/170_knn_search_hex_encoded_byte_vectors.yml index be1e619d046ac..c4d8b1f0929b0 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/170_knn_search_hex_encoded_byte_vectors.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/170_knn_search_hex_encoded_byte_vectors.yml @@ -164,8 +164,8 @@ setup: --- "Dynamic dimensions for hex-encoded string": - requires: - cluster_features: "gte_v8.15.0" - reason: 'hex encoding for byte vectors fixed in 8.15' + cluster_features: "gte_v8.14.1" + reason: 'hex encoding for byte vectors fixed in 8.14.1' - do: indices.create: From b97d5cfdb746605f722dead3aff3e7a122590ded Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 11 Jun 2024 08:15:37 -0400 Subject: [PATCH 05/18] Test mute for DenseVectorMappingUpdateIT #109571 (#109572) --- muted-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index d82c823f664be..eeafea033fc8a 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -62,6 +62,8 @@ tests: - class: "org.elasticsearch.smoketest.DocsClientYamlTestSuiteIT" issue: "https://github.com/elastic/elasticsearch/issues/109478" method: "test {yaml=reference/esql/processing-commands/lookup/line_31}" +- class: DenseVectorMappingUpdateIT + issue: "https://github.com/elastic/elasticsearch/issues/109571" # Examples: # From d6fb5cfbe6b8a519c18b0d4d952a8fee0c65e8c0 Mon Sep 17 00:00:00 2001 From: Liam Thompson <32779855+leemthompo@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:59:40 +0200 Subject: [PATCH 06/18] [DOCS] Expand context about `xpack.security.enabled` setting (#109575) --- docs/reference/settings/security-settings.asciidoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference/settings/security-settings.asciidoc b/docs/reference/settings/security-settings.asciidoc index e0d01965479ce..7dd9d0574638c 100644 --- a/docs/reference/settings/security-settings.asciidoc +++ b/docs/reference/settings/security-settings.asciidoc @@ -23,7 +23,9 @@ For more information about creating and updating the {es} keystore, see ==== General security settings `xpack.security.enabled`:: (<>) -Defaults to `true`, which enables {es} {security-features} on the node. + +Defaults to `true`, which enables {es} {security-features} on the node. +This setting must be enabled to use Elasticsearch's authentication, +authorization and audit features. + + -- If set to `false`, {security-features} are disabled, which is not recommended. From 71d2faa631f183511b0612cc004c08df0f695d32 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gomulka Date: Tue, 11 Jun 2024 15:05:02 +0200 Subject: [PATCH 07/18] Remove :qa:apm module (#109565) the test was disabled due to problem with availability of docker images after the release. It was reimplemented in :test:external-modules:apm-integration TracesApmIT closes #90308 --- qa/apm/build.gradle | 44 ---- qa/apm/config/elasticsearch/roles.yml | 34 --- qa/apm/config/elasticsearch/service_tokens | 2 - qa/apm/config/elasticsearch/users | 9 - qa/apm/config/elasticsearch/users_roles | 13 -- qa/apm/config/kibana/kibana-8.yml | 78 ------- qa/apm/docker-compose.yml | 154 ------------- qa/apm/scripts/tls/apm-server/cert.crt | 27 --- qa/apm/scripts/tls/apm-server/key.pem | 52 ----- .../elasticsearch/telemetry/apm/ApmIT.java | 210 ------------------ 10 files changed, 623 deletions(-) delete mode 100644 qa/apm/build.gradle delete mode 100644 qa/apm/config/elasticsearch/roles.yml delete mode 100644 qa/apm/config/elasticsearch/service_tokens delete mode 100644 qa/apm/config/elasticsearch/users delete mode 100644 qa/apm/config/elasticsearch/users_roles delete mode 100644 qa/apm/config/kibana/kibana-8.yml delete mode 100644 qa/apm/docker-compose.yml delete mode 100644 qa/apm/scripts/tls/apm-server/cert.crt delete mode 100644 qa/apm/scripts/tls/apm-server/key.pem delete mode 100644 qa/apm/src/test/java/org/elasticsearch/telemetry/apm/ApmIT.java diff --git a/qa/apm/build.gradle b/qa/apm/build.gradle deleted file mode 100644 index ff22334462fdc..0000000000000 --- a/qa/apm/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import org.elasticsearch.gradle.Architecture -import org.elasticsearch.gradle.VersionProperties -import org.elasticsearch.gradle.internal.info.BuildParams - -import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER - -apply plugin: 'elasticsearch.standalone-rest-test' -apply plugin: 'elasticsearch.test.fixtures' -apply plugin: 'elasticsearch.internal-distribution-download' - -dockerCompose { - environment.put 'STACK_VERSION', BuildParams.snapshotBuild ? VersionProperties.elasticsearch : VersionProperties.elasticsearch + "-SNAPSHOT" -} - -elasticsearch_distributions { - docker { - type = DOCKER - architecture = Architecture.current() - version = VersionProperties.getElasticsearch() - failIfUnavailable = false // This ensures we skip this testing if Docker is unavailable - } -} - -tasks.named("preProcessFixture").configure { - dependsOn elasticsearch_distributions.matching { it.architecture == Architecture.current() } -} - -tasks.register("integTest", Test) { - outputs.doNotCacheIf('Build cache is disabled for Docker tests') { true } - maxParallelForks = '1' - include '**/*IT.class' -} - -tasks.named("check").configure { - dependsOn "integTest" -} diff --git a/qa/apm/config/elasticsearch/roles.yml b/qa/apm/config/elasticsearch/roles.yml deleted file mode 100644 index 91277fa8dd65d..0000000000000 --- a/qa/apm/config/elasticsearch/roles.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -apm_server: - cluster: ['manage_ilm', 'manage_security', 'manage_api_key'] - indices: - - names: ['apm-*', 'logs-apm*', 'metrics-apm*', 'traces-apm*'] - privileges: ['write', 'create_index', 'manage', 'manage_ilm'] - applications: - - application: 'apm' - privileges: ['sourcemap:write', 'event:write', 'config_agent:read'] - resources: '*' -beats: - cluster: ['manage_index_templates', 'monitor', 'manage_ingest_pipelines', 'manage_ilm', 'manage_security', 'manage_api_key'] - indices: - - names: ['filebeat-*', 'shrink-filebeat-*'] - privileges: ['all'] -filebeat: - cluster: ['manage_index_templates', 'monitor', 'manage_ingest_pipelines', 'manage_ilm'] - indices: - - names: ['filebeat-*', 'shrink-filebeat-*'] - privileges: ['all'] -heartbeat: - cluster: ['manage_index_templates', 'monitor', 'manage_ingest_pipelines', 'manage_ilm'] - indices: - - names: ['heartbeat-*', 'shrink-heartbeat-*'] - privileges: ['all'] -metricbeat: - cluster: ['manage_index_templates', 'monitor', 'manage_ingest_pipelines', 'manage_ilm'] - indices: - - names: ['metricbeat-*', 'shrink-metricbeat-*'] - privileges: ['all'] -opbeans: - indices: - - names: ['opbeans-*'] - privileges: ['write', 'read'] diff --git a/qa/apm/config/elasticsearch/service_tokens b/qa/apm/config/elasticsearch/service_tokens deleted file mode 100644 index 02c39a69bc9bf..0000000000000 --- a/qa/apm/config/elasticsearch/service_tokens +++ /dev/null @@ -1,2 +0,0 @@ -elastic/fleet-server/elastic-package-fleet-server-token:{PBKDF2_STRETCH}10000$PNiVyY96dHwRfoDszBvYPAz+mSLbC+NhtPh63dblDZU=$dAY1tXX1U5rXB+2Lt7m0L2LUNSb1q5nRaIqPNZTBxb8= -elastic/kibana/elastic-package-kibana-token:{PBKDF2_STRETCH}10000$wIEFHIIIZ2ap0D0iQsyw0MfB7YuFA1bHnXAmlCoL4Gg=$YxvIJnasjLZyDQZpmFBiJHdR/CGXd5BnVm013Jty6p0= diff --git a/qa/apm/config/elasticsearch/users b/qa/apm/config/elasticsearch/users deleted file mode 100644 index 4cc30a99d92f1..0000000000000 --- a/qa/apm/config/elasticsearch/users +++ /dev/null @@ -1,9 +0,0 @@ -admin:$2a$10$xiY0ZzOKmDDN1p3if4t4muUBwh2.bFHADoMRAWQgSClm4ZJ4132Y. -apm_server_user:$2a$10$iTy29qZaCSVn4FXlIjertuO8YfYVLCbvoUAJ3idaXfLRclg9GXdGG -apm_user_ro:$2a$10$hQfy2o2u33SapUClsx8NCuRMpQyHP9b2l4t3QqrBA.5xXN2S.nT4u -beats_user:$2a$10$LRpKi4/Q3Qo4oIbiu26rH.FNIL4aOH4aj2Kwi58FkMo1z9FgJONn2 -filebeat_user:$2a$10$sFxIEX8tKyOYgsbJLbUhTup76ssvSD3L4T0H6Raaxg4ewuNr.lUFC -heartbeat_user:$2a$10$nKUGDr/V5ClfliglJhfy8.oEkjrDtklGQfhd9r9NoFqQeoNxr7uUK -kibana_system_user:$2a$10$nN6sRtQl2KX9Gn8kV/.NpOLSk6Jwn8TehEDnZ7aaAgzyl/dy5PYzW -metricbeat_user:$2a$10$5PyTd121U2ZXnFk9NyqxPuLxdptKbB8nK5egt6M5/4xrKUkk.GReG -opbeans_user:$2a$10$iTy29qZaCSVn4FXlIjertuO8YfYVLCbvoUAJ3idaXfLRclg9GXdGG diff --git a/qa/apm/config/elasticsearch/users_roles b/qa/apm/config/elasticsearch/users_roles deleted file mode 100644 index 629fe7392c12f..0000000000000 --- a/qa/apm/config/elasticsearch/users_roles +++ /dev/null @@ -1,13 +0,0 @@ -apm_server:apm_server_user -apm_system:apm_server_user -apm_user:apm_server_user,apm_user_ro -beats:beats_user -beats_system:beats_user,filebeat_user,heartbeat_user,metricbeat_user -filebeat:filebeat_user -heartbeat:heartbeat_user -ingest_admin:apm_server_user -kibana_system:kibana_system_user -kibana_user:apm_server_user,apm_user_ro,beats_user,filebeat_user,heartbeat_user,metricbeat_user,opbeans_user -metricbeat:metricbeat_user -opbeans:opbeans_user -superuser:admin diff --git a/qa/apm/config/kibana/kibana-8.yml b/qa/apm/config/kibana/kibana-8.yml deleted file mode 100644 index 4b3add76282d8..0000000000000 --- a/qa/apm/config/kibana/kibana-8.yml +++ /dev/null @@ -1,78 +0,0 @@ -xpack.fleet.packages: - - name: system - version: latest - - name: elastic_agent - version: latest - - name: apm - version: latest - - name: fleet_server - version: latest - -xpack.fleet.agentPolicies: - - name: Fleet Server + APM policy - id: fleet-server-apm-policy - description: Fleet server policy with APM and System logs and metrics enabled - namespace: default - is_default_fleet_server: true - is_managed: false - monitoring_enabled: - - logs - - metrics - package_policies: - - name: system-1 - package: - name: system - - name: apm-1 - package: - name: apm - inputs: - - type: apm - keep_enabled: true - vars: - - name: host - value: 0.0.0.0:8200 - frozen: true - - name: url - value: "${ELASTIC_APM_SERVER_URL}" - frozen: true - - name: enable_rum - value: true - frozen: true - - name: read_timeout - value: 1m - frozen: true - - name: shutdown_timeout - value: 2m - frozen: true - - name: write_timeout - value: 1m - frozen: true - - name: rum_allow_headers - value: - - x-custom-header - frozen: true - - name: secret_token - value: "${ELASTIC_APM_SECRET_TOKEN}" - frozen: true - - name: tls_enabled - value: ${ELASTIC_APM_TLS} - frozen: true - - name: tls_certificate - value: /usr/share/apmserver/config/certs/tls.crt - frozen: true - - name: tls_key - value: /usr/share/apmserver/config/certs/tls.key - frozen: true - - name: Fleet Server - package: - name: fleet_server - inputs: - - type: fleet-server - keep_enabled: true - vars: - - name: host - value: 0.0.0.0 - frozen: true - - name: port - value: 8220 - frozen: true diff --git a/qa/apm/docker-compose.yml b/qa/apm/docker-compose.yml deleted file mode 100644 index a3969479d0914..0000000000000 --- a/qa/apm/docker-compose.yml +++ /dev/null @@ -1,154 +0,0 @@ -version: "2.4" - -networks: - default: - name: apm-integration-testing - -services: - apmserver: - depends_on: - kibana: - condition: service_healthy - environment: - FLEET_ELASTICSEARCH_HOST: null - FLEET_SERVER_ELASTICSEARCH_INSECURE: "1" - FLEET_SERVER_ENABLE: "1" - FLEET_SERVER_HOST: 0.0.0.0 - FLEET_SERVER_INSECURE_HTTP: "1" - FLEET_SERVER_POLICY_ID: fleet-server-apm-policy - FLEET_SERVER_PORT: "8220" - FLEET_SERVER_SERVICE_TOKEN: AAEAAWVsYXN0aWMvZmxlZXQtc2VydmVyL2VsYXN0aWMtcGFja2FnZS1mbGVldC1zZXJ2ZXItdG9rZW46bmgtcFhoQzRRQ2FXbms2U0JySGlWQQ - KIBANA_FLEET_HOST: null - KIBANA_FLEET_SERVICE_TOKEN: AAEAAWVsYXN0aWMvZmxlZXQtc2VydmVyL2VsYXN0aWMtcGFja2FnZS1mbGVldC1zZXJ2ZXItdG9rZW46bmgtcFhoQzRRQ2FXbms2U0JySGlWQQ - KIBANA_FLEET_SETUP: "1" - healthcheck: - test: /bin/true - image: docker.elastic.co/beats/elastic-agent:${STACK_VERSION} - labels: - - co.elastic.apm.stack-version=${STACK_VERSION} - logging: - driver: json-file - options: - max-file: "5" - max-size: 2m - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./scripts/tls/apmserver/cert.crt:/usr/share/apmserver/config/certs/tls.crt - - ./scripts/tls/apmserver/key.pem:/usr/share/apmserver/config/certs/tls.key - - elasticsearch: - environment: - - action.destructive_requires_name=false - - bootstrap.memory_lock=true - - cluster.name=docker-cluster - - cluster.routing.allocation.disk.threshold_enabled=false - - discovery.type=single-node - - ES_JAVA_OPTS=-Xms1g -Xmx1g - - indices.id_field_data.enabled=true - - ingest.geoip.downloader.enabled=false - - path.repo=/usr/share/elasticsearch/data/backups - - xpack.license.self_generated.type=trial - - xpack.monitoring.collection.enabled=true - - xpack.security.authc.anonymous.roles=remote_monitoring_collector - - xpack.security.authc.api_key.enabled=true - - xpack.security.authc.realms.file.file1.order=0 - - xpack.security.authc.realms.native.native1.order=1 - - xpack.security.authc.token.enabled=true - - xpack.security.enabled=true - # APM specific settings. We don't configure `secret_key` because Kibana is configured with a blank key - - telemetry.tracing.enabled=true - - telemetry.agent.server_url=http://apmserver:8200 - # Send traces to APM server aggressively - - telemetry.agent.metrics_interval=1s - # Record everything - - telemetry.agent.transaction_sample_rate=1 - - telemetry.agent.log_level=debug - healthcheck: - interval: 20s - retries: 10 - test: curl -s -k http://localhost:9200/_cluster/health | grep -vq '"status":"red"' - image: elasticsearch:test - labels: - - co.elastic.apm.stack-version=${STACK_VERSION} - - co.elastic.metrics/module=elasticsearch - - co.elastic.metrics/metricsets=node,node_stats - - co.elastic.metrics/hosts=http://$${data.host}:9200 - logging: - driver: json-file - options: - max-file: "5" - max-size: 2m - ports: - # - 127.0.0.1:9200:9200 - - "9200" - ulimits: - memlock: - hard: -1 - soft: -1 - volumes: - - ./config/elasticsearch/roles.yml:/usr/share/elasticsearch/config/roles.yml - - ./config/elasticsearch/users:/usr/share/elasticsearch/config/users - - ./config/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles - - ./config/elasticsearch/service_tokens:/usr/share/elasticsearch/config/service_tokens - - kibana: - depends_on: - elasticsearch: - condition: service_healthy - environment: - ELASTICSEARCH_HOSTS: http://elasticsearch:9200 - ELASTICSEARCH_PASSWORD: changeme - ELASTICSEARCH_USERNAME: kibana_system_user - ELASTIC_APM_SECRET_TOKEN: "" - ELASTIC_APM_SERVER_URL: http://apmserver:8200 - ELASTIC_APM_TLS: "false" - SERVER_HOST: 0.0.0.0 - SERVER_NAME: kibana.example.org - STATUS_ALLOWANONYMOUS: "true" - TELEMETRY_ENABLED: "false" - XPACK_APM_SERVICEMAPENABLED: "true" - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: fhjskloppd678ehkdfdlliverpoolfcr - XPACK_FLEET_AGENTS_ELASTICSEARCH_HOSTS: '["http://elasticsearch:9200"]' - # XPACK_FLEET_REGISTRYURL: https://epr-snapshot.elastic.co - XPACK_MONITORING_ENABLED: "true" - XPACK_REPORTING_ROLES_ENABLED: "false" - XPACK_SECURITY_ENCRYPTIONKEY: fhjskloppd678ehkdfdlliverpoolfcr - XPACK_SECURITY_LOGINASSISTANCEMESSAGE: Login details: `admin/changeme`. Further details [here](https://github.com/elastic/apm-integration-testing#logging-in). - XPACK_SECURITY_SESSION_IDLETIMEOUT: 1M - XPACK_SECURITY_SESSION_LIFESPAN: 3M - XPACK_XPACK_MAIN_TELEMETRY_ENABLED: "false" - healthcheck: - interval: 10s - retries: 30 - start_period: 10s - test: curl -s -k http://kibana:5601/api/status | grep -q 'All services are available' - image: docker.elastic.co/kibana/kibana:${STACK_VERSION} - labels: - - co.elastic.apm.stack-version=${STACK_VERSION} - logging: - driver: json-file - options: - max-file: "5" - max-size: 2m - # ports: - # - 127.0.0.1:5601:5601 - volumes: - - ./config/kibana/kibana-8.yml:/usr/share/kibana/config/kibana.yml - - # Rather than mess aroud with threads in the test, just run `curl` in a - # loop to generate traces with a known path - tracegenerator: - depends_on: - apmserver: - condition: service_healthy - elasticsearch: - condition: service_healthy - kibana: - condition: service_healthy - # Official curl image - image: curlimages/curl - command: /bin/sh -c "while true; do curl -s -k -u admin:changeme http://elasticsearch:9200/_nodes/stats >/dev/null ; sleep 3; done" - -volumes: - esdata: - driver: local diff --git a/qa/apm/scripts/tls/apm-server/cert.crt b/qa/apm/scripts/tls/apm-server/cert.crt deleted file mode 100644 index b2f9aa7b5d230..0000000000000 --- a/qa/apm/scripts/tls/apm-server/cert.crt +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEpjCCAo4CCQDR9oXvJbopHjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDAph -cG0tc2VydmVyMB4XDTE5MTExOTE1MjE0NVoXDTI5MTExNjE1MjE0NVowFTETMBEG -A1UEAwwKYXBtLXNlcnZlcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANduj3tyeBIHj0Bf5aKMRImhRbkAaQ2p6T0WsHKlicd1P4/D5l783+vVsbwprRqR -qXAUsUWcUSYJXBX1qtC2MtKqi4xYUTAyQV5dgrMoCV+vtZY31SK4kolumd1vVMh+ -po+IwueLvLMFK1tQGIXlJblSDYVauIt5rp79IIhWOY/YpcQy9RaxykljTYTbPjLW -m3T92bow1nLh5GL3ThJEAkLO+hkJv9716+YRWYtPcojiGzpLjFgF50MoP4Lilm9U -r2tBnqpvb2PwE1kkly8DDBtcg+HM4tgGsbdWo2Pgp82ARV4DL+JlNJ+SVQZAmTbc -3LMwxnUJtuKMeh2rwb9HOyuONXfF1PiEzyDhAlabyS6toAGy1mlMAop1ClO1wV5O -Ayy47TeD6ziNyMKB7/XHdW4rb16K6j6EV27Bg2ZK6Vrfkwm3aRbpztfVRMX+HMUp -ktH+V2OwJoP7l7lzw/q8yMdopG57zRJa1dx8NWP/UKi8Ej+87DYyWJODiNHD7PM7 -9vfd47lNcWxw+p7ntEpnn6EeW2r7SlmfhtdIxL2DiTiKAq9Ktyi9cFnGnDfSDJST -T1G1vIDdG33Vt2Y5+wqzCGbYyMsAOaMdXZSeniXXFR4GX7iz+AGoKojBbmoo9VqP -mvbudNU+ysha4IJvTfOczJZgstxCXG+MXbEXFSgysImFAgMBAAEwDQYJKoZIhvcN -AQELBQADggIBAFh2YxRT6PaAXDq38rm25I91fCP9PzVPDuIkn9wl85e7avuh6FZi -R0nQG6+lB1i8XSm9UMl9+ISjE+EQqry6KB6mDsakGOsDuEUdZiw3sGJIUWQkQArB -ym5DqxKpeZBeVHBxnrEbQBV8s0j8uxd7X1E0ImfMKbKfNr/B5qPRXkREvydLWYvq -8yMcUPu1MiZFUgAGr9Py39kW3lbRPWZii/2bN8AB9h6gAhq5TiennfgJZsRiuSta -w/TmOcAuz4e/KPIzfvL/YCWbLyJ2vrIQeOc4N7jZfqMmLKgYCRyjI7+amfuyKPBW -J4psfJ0ssHdTxAUK65vghJ2s6FLvU3HoxzetZsJp5kj6CKYaFYkB4NkkYnlY8MP/ -T68oOmdYwwwrcBmDtZwoppRb5zhev5k3aykgZ/B/vqVJE9oIPkp/7wqEP1WqSiUe -AgyQBu8UN4ho2Rf6nZezZ4cjW/0WyhGOHQBFmwPI2MBGsQxF2PF4lKkJtaywIEm7 -4UsEQYK7Hf2J2OccWGvfo5HZ5tsSbuOGAf0bfHfaBQBsvzWet+TO6XX9VrWjnAKl -bH+mInmnd9v2oABFl9Djv/Cw+lEAxxkCTW+DcwdEFJREPab5xhQDEpQQ/Ef0ihvg -/ZtJQeoOYfrLN6K726QmoRWxvqxLyWK3gztcO1svHqr/cMt3ooLJEaqU ------END CERTIFICATE----- diff --git a/qa/apm/scripts/tls/apm-server/key.pem b/qa/apm/scripts/tls/apm-server/key.pem deleted file mode 100644 index 31208905f7d78..0000000000000 --- a/qa/apm/scripts/tls/apm-server/key.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDXbo97cngSB49A -X+WijESJoUW5AGkNqek9FrBypYnHdT+Pw+Ze/N/r1bG8Ka0akalwFLFFnFEmCVwV -9arQtjLSqouMWFEwMkFeXYKzKAlfr7WWN9UiuJKJbpndb1TIfqaPiMLni7yzBStb -UBiF5SW5Ug2FWriLea6e/SCIVjmP2KXEMvUWscpJY02E2z4y1pt0/dm6MNZy4eRi -904SRAJCzvoZCb/e9evmEVmLT3KI4hs6S4xYBedDKD+C4pZvVK9rQZ6qb29j8BNZ -JJcvAwwbXIPhzOLYBrG3VqNj4KfNgEVeAy/iZTSfklUGQJk23NyzMMZ1CbbijHod -q8G/RzsrjjV3xdT4hM8g4QJWm8kuraABstZpTAKKdQpTtcFeTgMsuO03g+s4jcjC -ge/1x3VuK29eiuo+hFduwYNmSula35MJt2kW6c7X1UTF/hzFKZLR/ldjsCaD+5e5 -c8P6vMjHaKRue80SWtXcfDVj/1CovBI/vOw2MliTg4jRw+zzO/b33eO5TXFscPqe -57RKZ5+hHltq+0pZn4bXSMS9g4k4igKvSrcovXBZxpw30gyUk09RtbyA3Rt91bdm -OfsKswhm2MjLADmjHV2Unp4l1xUeBl+4s/gBqCqIwW5qKPVaj5r27nTVPsrIWuCC -b03znMyWYLLcQlxvjF2xFxUoMrCJhQIDAQABAoICAQCfClIGsoUN2mLZBXLDw4W9 -jT+pyjHEEpHLtXphyO+kPlzER71Elq7AriveW24d1TcfNUeBulr2F6bR12FZX4i5 -mYoX/AND73Xusl4Q4Re6ej82PNWuIlCcAPi6Trxqn4VbJX2t7q1KBCDz8neIMZjd -7UNqFYV0Akr1uK1RuUYZebk21N+29139O8A4upp6cZCml9kq6W8HtNgkb6pFNcvt -gluELHxnn2mdmWVfwTEu+K1dJfTf7svB+m6Ys6qXWg9+wRzfehDj2JKQFsE9xaQk -dvItulIlZRvB28YXr/xxa6bKNtQc8NYej6sRSJNTu017RCDeumM3cLmeOfR4v59f -tkMWnFcA3ykmsaK2FiQyX+MoWvs5vdT7/yNIfz3a4MErcWg8z3FDbffKfbhgsb+2 -z4Ub6fIRKZykW2ajN7t0378bMmJ3rPT66QF40aNNeWasF3EHcwekDPpsHIBJoY4G -9aG6uTUmRkC+NGeP9HroxkvDo2NbXn8XGOEJS64rwsME3CsUi1A5ZY0XLTxYptH6 -X2TfC5oTmnsYB/wWqo26bTJc0bwDOueQWYap0aVtv3f/0tzueKepCbxdeG4ikA0U -2t3F+OUmoCZ5D0p+6zLvrTUPhPCFEynp+vGUvmbwozYi0NWzFyFqlvqRG1KLIVLG -ZRyTMYuZ/cWkv1SJYbEcaQKCAQEA/9HaJg2YACv7rx6/FesE/81u16OYTaahHngW -4M+5rT0+fNKYH/fYkwavQ/Gr6FSTls7F+8K9DVwoGLZRQ3t6epCXqGqX0uaY+iSH -O8eezXVnHzUaVE4KlwJY9xZ+K1iIf5zUb5hpaQI0jKS/igcxFAsutWiyenrz8eQp -MAycZmzkQMLbUsa1t6y0VaEaC4YMHyQ9ag2eMfqbG27plFQbYxllHXowGMFXPheY -xACwo5V5tJUgRP+HlrI4rf0vadMgVIKxVSUiqIzGREIkYrTAshFjkpHR5/R8s/kH -Xm8q2gdoJltBFJzA2B8MHXVi7mYDBlUmBoRKhzkl/TSray9j7wKCAQEA15VsNQZu -cZluboz/R4EDbEm1po2UBcNNiu/fgJ8BDUkLzJESIITY41fgvBbTun1fiuGeE+El -0o1w4hQhIiV1KAB44w69fJR0VELfMZiIcd8kd0sDgPPVrd1MzzKPZ9yg4mbEkCCO -V/EoTi8Ut27sMcl8059qm1qq7I5pzHwSziNa087m+5VdfmvJZJVipudngZ3QmRgU -KKcBhgFFSkncYezoq2XQfRcqkk0sORxDvsMmRInyHZh0l9zv46ihgTvErlCHtizV -V4HNO4OPz7FxUZ04iWSGZs4snu1cW2j+lbKuOkADveBYVmCcdZ3R0SH+A5skL0zG -tm6z0TNP/kFlywKCAQEA+lTdFu2od0qTADujG4yemL7rn2J8EEhlU86J/LXo6UiM -FFNz/5xltwIMkf00jqXswt9WR9W5cBBlQEFwZgu3v6YscebU6NE0k1sZZnshv8YK -AjTRrfusSzdF3YyKLFp3QAE0tHs9cz9wMsyojiYZdZa3v1dTh503h9YQI+/DQEuA -VIsZWfgPLEx5L231cZ9bz0GEQ3pN+nRUQdUYB0kCf8gC9YRy+lZ/y8gFeo9+SqVj -sj1XlY1DnkiKRGAEfJbYBTra0woCz1LqVTMwLdLY2adAe9XrxQKu4OJovpUkJrSm -yxnzJnt6DkLbdRxAki8K+LBsBGaCE67tqMhYkguOywKCAQAslEl77YiJFSEw2xcu -wg7jJZrahgxF5Mz0HgYporek96Xo91a4QsBWwqVGP7IoriRDo8P8eGJJ19Wv6lmv -pe9EBlT5HuMwD8K+adWde907Ltlrkad30vQsr8ZiUiI1Z/oc1wNuikzlAolDIZk3 -FUjiQrf9SsnQtj8CC7D1B/MbjVQK2I4LGCftLHzIv9tWiCNvOiMYhVIl1eMKwtiB -NCTOWx8B0lv6gf/boPm0FZQsrk4LfjsCw7PYc2dnvEcpYiKZqS1nDn5PShgWZm4m -lJrKNairQI5KU/gGJS8j9+ItMnW0tegQK4QY2IGCENCCXnUYacxhu46byuiEKggw -m3VhAoIBAQCQa90StsZHqZ+J83do3kpvD+O5nURPnckznC2WJgraW49k5vltnJTT -zkFTqHMLfmYwAz1o15sPCqlkMD+fEUzg6Hpzxm7dOUppkf5KFbD7AnsYU9U8LamJ -HaET7Dq5TpjG7uoaHZZjs7cCHcWu2E8nIezyAtZ+rbTg/qW7bYMAlJTkerznGuDU -v0hNzCr/81o5rbX0UhetcmKVOprUSWzfrw5ElLhAtzM7zivbZSnsOny8pC33FtQ5 -iQbVcNGUjfFCM95ZipxxN9z0FwxpJ1paCPGYA86u2olWl/VnVPqEj7WYzO8H5W2q -aXpWH6HVf6B10pQrWWwUAAHyqYS5bZkQ ------END PRIVATE KEY----- diff --git a/qa/apm/src/test/java/org/elasticsearch/telemetry/apm/ApmIT.java b/qa/apm/src/test/java/org/elasticsearch/telemetry/apm/ApmIT.java deleted file mode 100644 index 021d9f8d01bf3..0000000000000 --- a/qa/apm/src/test/java/org/elasticsearch/telemetry/apm/ApmIT.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.telemetry.apm; - -import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; -import org.elasticsearch.common.settings.SecureString; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.common.xcontent.support.XContentMapValues; -import org.elasticsearch.core.CheckedRunnable; -import org.elasticsearch.test.rest.ESRestTestCase; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasKey; -import static org.hamcrest.Matchers.not; - -/** - * Tests around Elasticsearch's tracing support using APM. - */ -public class ApmIT extends ESRestTestCase { - - private static final String DATA_STREAM = "traces-apm-default"; - - /** - * Check that if we send HTTP traffic to Elasticsearch, then traces are captured in APM server. The traces are generated in - * a separate Docker container, which continually fetches `/_nodes/stats`. We check for the following: - *

- *

This proves that the hierarchy of spans is being correctly captured. - */ - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/90308") - public void testCapturesTracesForHttpTraffic() throws Exception { - checkTracesDataStream(); - - assertTracesExist(); - } - - private void checkTracesDataStream() throws Exception { - assertBusy(() -> { - final Response response = performRequestTolerantly(new Request("GET", "/_data_stream/" + DATA_STREAM)); - assertOK(response); - }, 1, TimeUnit.MINUTES); - } - - private void assertTracesExist() throws Exception { - // First look for a transaction for the REST calls that we make via the `tracegenerator` Docker container - - final AtomicReference transactionId = new AtomicReference<>(); - assertBusy(() -> { - final Request tracesSearchRequest = new Request("GET", "/" + DATA_STREAM + "/_search"); - tracesSearchRequest.setJsonEntity(""" - { - "query": { - "match": { "transaction.name": "GET /_nodes/stats" } - } - }"""); - final Response tracesSearchResponse = performRequestTolerantly(tracesSearchRequest); - assertOK(tracesSearchResponse); - - final List> documents = getDocuments(tracesSearchResponse); - assertThat(documents, not(empty())); - - final Map tx = documents.get(0); - - check(tx, "http.request.method", "GET"); - check(tx, "http.response.status_code", 200); - check(tx, "labels.es_cluster_name", "docker-cluster"); - check(tx, "labels.http_request_headers_authorization", "[REDACTED]"); - check(tx, "span.kind", "SERVER"); - check(tx, "transaction.result", "HTTP 2xx"); - check(tx, "url.path", "/_nodes/stats"); - - final String txId = pluck(tx, "transaction.id"); - transactionId.set(txId); - }, 1, TimeUnit.MINUTES); - - // Then look for the task that the REST call starts - - final AtomicReference monitorNodeStatsSpanId = new AtomicReference<>(); - assertBusy(() -> { - final List> documents = searchByParentId(transactionId.get()); - assertThat(documents, not(empty())); - - final Map spansByName = documents.stream().collect(Collectors.toMap(d -> pluck(d, "span.name"), d -> d)); - - assertThat(spansByName, hasKey("cluster:monitor/nodes/stats")); - - @SuppressWarnings("unchecked") - final Map span = (Map) spansByName.get("cluster:monitor/nodes/stats"); - check(span, "span.kind", "INTERNAL"); - - final String spanId = pluck(span, "span.id"); - monitorNodeStatsSpanId.set(spanId); - }, 1, TimeUnit.MINUTES); - - // Finally look for the child task that the task above started - - assertBusy(() -> { - final List> documents = searchByParentId(monitorNodeStatsSpanId.get()); - assertThat(documents, not(empty())); - - final Map spansByName = documents.stream().collect(Collectors.toMap(d -> pluck(d, "span.name"), d -> d)); - - assertThat(spansByName, hasKey("cluster:monitor/nodes/stats[n]")); - }, 1, TimeUnit.MINUTES); - } - - @SuppressWarnings("unchecked") - private T pluck(Map map, String path) { - String[] parts = path.split("\\."); - - Object result = map; - - for (String part : parts) { - result = ((Map) result).get(part); - } - - return (T) result; - } - - private List> searchByParentId(String parentId) throws IOException { - final Request searchRequest = new Request("GET", "/" + DATA_STREAM + "/_search"); - searchRequest.setJsonEntity(""" - { - "query": { - "match": { "parent.id": "%s" } - } - }""".formatted(parentId)); - final Response response = performRequestTolerantly(searchRequest); - assertOK(response); - - return getDocuments(response); - } - - /** - * We don't need to clean up the cluster, particularly as we have Kibana and APM server using ES as well as our test, so declare - * that we need to preserve the cluster in order to prevent the usual cleanup logic from running (and inevitably failing). - */ - @Override - protected boolean preserveClusterUponCompletion() { - return true; - } - - /** - * Turns exceptions into assertion failures so that {@link #assertBusy(CheckedRunnable)} can still retry. - */ - private Response performRequestTolerantly(Request request) { - try { - return client().performRequest(request); - } catch (Exception e) { - throw new AssertionError(e); - } - } - - /** - * Customizes the client settings to use the same username / password that is configured in Docke.r - */ - @Override - protected Settings restClientSettings() { - String token = basicAuthHeaderValue("admin", new SecureString("changeme".toCharArray())); - return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); - } - - /** - * Constructs the correct cluster address by looking up the dynamic port that Elasticsearch is exposed on. - */ - @Override - protected String getTestRestCluster() { - return "localhost:" + getProperty("test.fixtures.elasticsearch.tcp.9200"); - } - - @SuppressWarnings("unchecked") - private List> getDocuments(Response response) throws IOException { - final Map stringObjectMap = ESRestTestCase.entityAsMap(response); - return (List>) XContentMapValues.extractValue("hits.hits._source", stringObjectMap); - } - - private String getProperty(String key) { - String value = System.getProperty(key); - if (value == null) { - throw new IllegalStateException( - "Could not find system properties from test.fixtures. " - + "This test expects to run with the elasticsearch.test.fixtures Gradle plugin" - ); - } - return value; - } - - private void check(Map doc, String path, T expected) { - assertThat(pluck(doc, path), equalTo(expected)); - } -} From 854730d98ff717178ce76113513c6759757c0ac7 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Tue, 11 Jun 2024 15:08:19 +0200 Subject: [PATCH 08/18] AwaitsFix: https://github.com/elastic/elasticsearch/issues/109578 --- muted-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index eeafea033fc8a..706a59882a20e 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -64,6 +64,9 @@ tests: method: "test {yaml=reference/esql/processing-commands/lookup/line_31}" - class: DenseVectorMappingUpdateIT issue: "https://github.com/elastic/elasticsearch/issues/109571" +- class: "org.elasticsearch.compute.lucene.TimeSeriesSortedSourceOperatorTests" + issue: "https://github.com/elastic/elasticsearch/issues/109578" + method: "testMatchNone" # Examples: # From 9098f777920aae4842185f2876f5a895f7a57080 Mon Sep 17 00:00:00 2001 From: Jedr Blaszyk Date: Tue, 11 Jun 2024 15:20:57 +0200 Subject: [PATCH 09/18] [Connector API] Allow for resetting connector error (#109573) --- .../connector/100_connector_update_error.yml | 30 +++++++++++++++++++ .../connector/ConnectorIndexService.java | 15 ++++++---- .../TransportUpdateConnectorErrorAction.java | 6 +++- .../action/UpdateConnectorErrorAction.java | 4 +-- .../connector/ConnectorIndexServiceTests.java | 17 ++++++++++- 5 files changed, 62 insertions(+), 10 deletions(-) diff --git a/x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/100_connector_update_error.yml b/x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/100_connector_update_error.yml index 5ca285677a95e..a58f2399301d3 100644 --- a/x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/100_connector_update_error.yml +++ b/x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/100_connector_update_error.yml @@ -30,6 +30,36 @@ setup: - match: { error: "some error" } + +--- +"Reset Connector Error": + + # Set error + - do: + connector.update_error: + connector_id: test-connector + body: + error: "some error" + + + - match: { result: updated } + + # Reset error to null + - do: + connector.update_error: + connector_id: test-connector + body: + error: null + + + - match: { result: updated } + + - do: + connector.get: + connector_id: test-connector + + - match: { error: null } + --- "Update Connector Error - 404 when connector doesn't exist": - do: diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java index e5314a20bdccf..bb03d3c69c74a 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java @@ -44,7 +44,6 @@ import org.elasticsearch.xpack.application.connector.action.ConnectorCreateActionResponse; import org.elasticsearch.xpack.application.connector.action.UpdateConnectorApiKeyIdAction; import org.elasticsearch.xpack.application.connector.action.UpdateConnectorConfigurationAction; -import org.elasticsearch.xpack.application.connector.action.UpdateConnectorErrorAction; import org.elasticsearch.xpack.application.connector.action.UpdateConnectorIndexNameAction; import org.elasticsearch.xpack.application.connector.action.UpdateConnectorLastSyncStatsAction; import org.elasticsearch.xpack.application.connector.action.UpdateConnectorNameAction; @@ -470,17 +469,21 @@ else if (configurationValues != null) { /** * Updates the error property of a {@link Connector}. * - * @param request The request for updating the connector's error. - * @param listener The listener for handling responses, including successful updates or errors. + * @param connectorId The ID of the {@link Connector} to be updated. + * @param error An instance of error property of {@link Connector}, can be reset to [null]. + * @param listener The listener for handling responses, including successful updates or errors. */ - public void updateConnectorError(UpdateConnectorErrorAction.Request request, ActionListener listener) { + public void updateConnectorError(String connectorId, String error, ActionListener listener) { try { - String connectorId = request.getConnectorId(); final UpdateRequest updateRequest = new UpdateRequest(CONNECTOR_INDEX_NAME, connectorId).doc( new IndexRequest(CONNECTOR_INDEX_NAME).opType(DocWriteRequest.OpType.INDEX) .id(connectorId) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .source(Map.of(Connector.ERROR_FIELD.getPreferredName(), request.getError())) + .source(new HashMap<>() { + { + put(Connector.ERROR_FIELD.getPreferredName(), error); + } + }) ); client.update(updateRequest, new DelegatingIndexNotFoundActionListener<>(connectorId, listener, (l, updateResponse) -> { if (updateResponse.getResult() == UpdateResponse.Result.NOT_FOUND) { diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/TransportUpdateConnectorErrorAction.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/TransportUpdateConnectorErrorAction.java index 7c279852625b2..d71344e74aee9 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/TransportUpdateConnectorErrorAction.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/TransportUpdateConnectorErrorAction.java @@ -41,6 +41,10 @@ protected void doExecute( UpdateConnectorErrorAction.Request request, ActionListener listener ) { - connectorIndexService.updateConnectorError(request, listener.map(r -> new ConnectorUpdateActionResponse(r.getResult()))); + connectorIndexService.updateConnectorError( + request.getConnectorId(), + request.getError(), + listener.map(r -> new ConnectorUpdateActionResponse(r.getResult())) + ); } } diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/UpdateConnectorErrorAction.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/UpdateConnectorErrorAction.java index e6485285e1998..ae86c1fc98df1 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/UpdateConnectorErrorAction.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/UpdateConnectorErrorAction.java @@ -28,7 +28,7 @@ import java.util.Objects; import static org.elasticsearch.action.ValidateActions.addValidationError; -import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg; +import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg; public class UpdateConnectorErrorAction { @@ -81,7 +81,7 @@ public ActionRequestValidationException validate() { ); static { - PARSER.declareStringOrNull(optionalConstructorArg(), Connector.ERROR_FIELD); + PARSER.declareStringOrNull(constructorArg(), Connector.ERROR_FIELD); } public static UpdateConnectorErrorAction.Request fromXContentBytes( diff --git a/x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java b/x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java index 698c061d1bd6c..a696c6e6dde54 100644 --- a/x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java +++ b/x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java @@ -725,6 +725,21 @@ public void testUpdateConnectorError() throws Exception { assertThat(updateErrorRequest.getError(), equalTo(indexedConnector.getError())); } + public void testUpdateConnectorError_resetWithNull() throws Exception { + Connector connector = ConnectorTestUtils.getRandomConnector(); + String connectorId = randomUUID(); + ConnectorCreateActionResponse resp = awaitCreateConnector(connectorId, connector); + assertThat(resp.status(), anyOf(equalTo(RestStatus.CREATED), equalTo(RestStatus.OK))); + + UpdateConnectorErrorAction.Request updateErrorRequest = new UpdateConnectorErrorAction.Request(connectorId, null); + + DocWriteResponse updateResponse = awaitUpdateConnectorError(updateErrorRequest); + assertThat(updateResponse.status(), equalTo(RestStatus.OK)); + + Connector indexedConnector = awaitGetConnector(connectorId); + assertThat(updateErrorRequest.getError(), equalTo(indexedConnector.getError())); + } + public void testUpdateConnectorNameOrDescription() throws Exception { Connector connector = ConnectorTestUtils.getRandomConnector(); String connectorId = randomUUID(); @@ -1336,7 +1351,7 @@ private UpdateResponse awaitUpdateConnectorError(UpdateConnectorErrorAction.Requ CountDownLatch latch = new CountDownLatch(1); final AtomicReference resp = new AtomicReference<>(null); final AtomicReference exc = new AtomicReference<>(null); - connectorIndexService.updateConnectorError(updatedError, new ActionListener<>() { + connectorIndexService.updateConnectorError(updatedError.getConnectorId(), updatedError.getError(), new ActionListener<>() { @Override public void onResponse(UpdateResponse indexResponse) { resp.set(indexResponse); From c6fe3c3efeb788a683cf6b1de8a47f0ee23dd91e Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 11 Jun 2024 09:26:04 -0400 Subject: [PATCH 10/18] ESQL: Improve syntax for LOOKUP tables (#109489) Replace the syntax for `tables` with something a little more natural. Now it is: ``` $ curl -uelastic:password -HContent-Type:application/json -XPOST \ 'localhost:9200/_query?error_trace&pretty&format=txt' \ -d'{ "query": "ROW a=1::LONG | LOOKUP t ON a", "tables": { "t": { "a": {"long": [ 1, 4, 2]}, "v1": {"integer": [ 10, 11, 12]}, "v2": {"keyword": ["cat", "dog", "wow"]} } } }' v1 | v2 | a ---------------+---------------+--------------- 10 |cat |1 ``` --- .../esql/processing-commands/lookup.asciidoc | 4 +- .../xpack/esql/qa/single_node/RestEsqlIT.java | 17 +++++ .../xpack/esql/qa/rest/EsqlSpecTestCase.java | 37 +++++++---- .../xpack/esql/qa/rest/RestEsqlTestCase.java | 18 ++++- .../xpack/esql/action/EsqlCapabilities.java | 5 ++ .../xpack/esql/action/ParseTables.java | 30 +++++---- .../esql/action/EsqlQueryRequestTests.java | 24 +++---- .../rest-api-spec/test/esql/150_lookup.yml | 65 +++++++------------ 8 files changed, 114 insertions(+), 86 deletions(-) diff --git a/docs/reference/esql/processing-commands/lookup.asciidoc b/docs/reference/esql/processing-commands/lookup.asciidoc index 5507c6cc29d1b..88f7570f753ca 100644 --- a/docs/reference/esql/processing-commands/lookup.asciidoc +++ b/docs/reference/esql/processing-commands/lookup.asciidoc @@ -40,8 +40,8 @@ POST /_query?format=txt """, "tables": { "era": { - "author:keyword": ["Frank Herbert", "Peter F. Hamilton", "Vernor Vinge", "Alastair Reynolds", "James S.A. Corey"], - "era:keyword" : [ "The New Wave", "Diamond", "Diamond", "Diamond", "Hadron"] + "author": {"keyword": ["Frank Herbert", "Peter F. Hamilton", "Vernor Vinge", "Alastair Reynolds", "James S.A. Corey"]}, + "era": {"keyword": [ "The New Wave", "Diamond", "Diamond", "Diamond", "Hadron"]} } } } diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java index 7c57212d0f574..bf54dcbfa96f6 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java @@ -256,6 +256,23 @@ public void testIncompatibleMappingsErrors() throws IOException { assertThat(deleteIndex("index2").isAcknowledged(), Matchers.is(true)); } + public void testTableDuplicateNames() throws IOException { + Request request = new Request("POST", "/_query"); + request.setJsonEntity(""" + { + "query": "FROM a=1", + "tables": { + "t": { + "a": {"integer": [1]}, + "a": {"integer": [1]} + } + } + }"""); + ResponseException re = expectThrows(ResponseException.class, () -> client().performRequest(request)); + assertThat(re.getResponse().getStatusLine().getStatusCode(), equalTo(400)); + assertThat(re.getMessage(), containsString("[6:10] Duplicate field 'a'")); + } + private void assertException(String query, String... errorMessages) throws IOException { ResponseException re = expectThrows(ResponseException.class, () -> runEsqlSync(requestObjectBuilder().query(query))); assertThat(re.getResponse().getStatusLine().getStatusCode(), equalTo(400)); diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java index a42f02a22aba8..3e7b1e927a9b7 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java @@ -321,43 +321,52 @@ public static void assertRequestBreakerEmpty() throws Exception { * "tables" parameter sent if there is a LOOKUP in the request. If you * add to this, you must also add to {@link EsqlTestUtils#tables}; */ - private Map>> tables() { - Map>> tables = new TreeMap<>(); + private Map> tables() { + Map> tables = new TreeMap<>(); tables.put( "int_number_names", EsqlTestUtils.table( - Map.entry("int:integer", IntStream.range(0, 10).boxed().toList()), - Map.entry("name:keyword", IntStream.range(0, 10).mapToObj(EsqlTestUtils::numberName).toList()) + Map.entry("int", new RestEsqlTestCase.TypeAndValues("integer", IntStream.range(0, 10).boxed().toList())), + Map.entry( + "name", + new RestEsqlTestCase.TypeAndValues("keyword", IntStream.range(0, 10).mapToObj(EsqlTestUtils::numberName).toList()) + ) ) ); tables.put( "long_number_names", EsqlTestUtils.table( - Map.entry("long:long", LongStream.range(0, 10).boxed().toList()), - Map.entry("name:keyword", IntStream.range(0, 10).mapToObj(EsqlTestUtils::numberName).toList()) + Map.entry("long", new RestEsqlTestCase.TypeAndValues("long", LongStream.range(0, 10).boxed().toList())), + Map.entry( + "name", + new RestEsqlTestCase.TypeAndValues("keyword", IntStream.range(0, 10).mapToObj(EsqlTestUtils::numberName).toList()) + ) ) ); tables.put( "double_number_names", EsqlTestUtils.table( - Map.entry("double:double", List.of(2.03, 2.08)), - Map.entry("name:keyword", List.of("two point zero three", "two point zero eight")) + Map.entry("double", new RestEsqlTestCase.TypeAndValues("double", List.of(2.03, 2.08))), + Map.entry("name", new RestEsqlTestCase.TypeAndValues("keyword", List.of("two point zero three", "two point zero eight"))) ) ); tables.put( "double_number_names_with_null", EsqlTestUtils.table( - Map.entry("double:double", List.of(2.03, 2.08, 0.0)), - Map.entry("name:keyword", Arrays.asList("two point zero three", "two point zero eight", null)) + Map.entry("double", new RestEsqlTestCase.TypeAndValues("double", List.of(2.03, 2.08, 0.0))), + Map.entry( + "name", + new RestEsqlTestCase.TypeAndValues("keyword", Arrays.asList("two point zero three", "two point zero eight", null)) + ) ) ); tables.put( "big", EsqlTestUtils.table( - Map.entry("aa:keyword", List.of("foo", "bar", "baz", "foo")), - Map.entry("ab:keyword", List.of("zoo", "zop", "zoi", "foo")), - Map.entry("na:integer", List.of(1, 10, 100, 2)), - Map.entry("nb:integer", List.of(-1, -10, -100, -2)) + Map.entry("aa", new RestEsqlTestCase.TypeAndValues("keyword", List.of("foo", "bar", "baz", "foo"))), + Map.entry("ab", new RestEsqlTestCase.TypeAndValues("keyword", List.of("zoo", "zop", "zoi", "foo"))), + Map.entry("na", new RestEsqlTestCase.TypeAndValues("integer", List.of(1, 10, 100, 2))), + Map.entry("nb", new RestEsqlTestCase.TypeAndValues("integer", List.of(-1, -10, -100, -2))) ) ); return tables; diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java index 349f9445030c4..0c5ec5eac716e 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java @@ -109,11 +109,13 @@ protected RestEsqlTestCase(Mode mode) { this.mode = mode; } + public record TypeAndValues(String type, List values) {} + public static class RequestObjectBuilder { private final XContentBuilder builder; private boolean isBuilt = false; - private Map>> tables; + private Map> tables; private Boolean keepOnCompletion = null; @@ -131,7 +133,7 @@ public RequestObjectBuilder query(String query) throws IOException { return this; } - public RequestObjectBuilder tables(Map>> tables) { + public RequestObjectBuilder tables(Map> tables) { this.tables = tables; return this; } @@ -181,7 +183,17 @@ public RequestObjectBuilder pragmas(Settings pragmas) throws IOException { public RequestObjectBuilder build() throws IOException { if (isBuilt == false) { if (tables != null) { - builder.field("tables", tables); + builder.startObject("tables"); + for (var table : tables.entrySet()) { + builder.startObject(table.getKey()); + for (var column : table.getValue().entrySet()) { + builder.startObject(column.getKey()); + builder.field(column.getValue().type(), column.getValue().values()); + builder.endObject(); + } + builder.endObject(); + } + builder.endObject(); } builder.endObject(); isBuilt = true; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 75600e64e3e90..9e8553911268f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -57,6 +57,11 @@ public class EsqlCapabilities { */ private static final String LOOKUP_COMMAND = "lookup_command"; + /** + * Support for the syntax {@code "tables": {"type": []}}. + */ + private static final String TABLES_TYPES = "tables_types"; + /** * Support for requesting the "REPEAT" command. */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ParseTables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ParseTables.java index 97728196a0ced..cc56285f3c78b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ParseTables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ParseTables.java @@ -83,17 +83,11 @@ private Map parseTable() throws IOException { return columns; } case FIELD_NAME -> { - String[] fname = p.currentName().split(":"); - if (fname.length != 2) { - throw new XContentParseException( - p.getTokenLocation(), - "expected columns named name:type but was [" + p.currentName() + "]" - ); + String name = p.currentName(); + if (columns.containsKey(name)) { + throw new XContentParseException(p.getTokenLocation(), "duplicate column name [" + name + "]"); } - if (columns.containsKey(fname[0])) { - throw new XContentParseException(p.getTokenLocation(), "duplicate column name [" + fname[0] + "]"); - } - columns.put(fname[0], parseColumn(fname[1])); + columns.put(name, parseColumn()); } default -> throw new XContentParseException( p.getTokenLocation(), @@ -108,14 +102,26 @@ private Map parseTable() throws IOException { } } - private Column parseColumn(String type) throws IOException { - return switch (type) { + private Column parseColumn() throws IOException { + if (p.nextToken() != XContentParser.Token.START_OBJECT) { + throw new XContentParseException(p.getTokenLocation(), "expected " + XContentParser.Token.START_OBJECT); + } + if (p.nextToken() != XContentParser.Token.FIELD_NAME) { + throw new XContentParseException(p.getTokenLocation(), "expected " + XContentParser.Token.FIELD_NAME); + } + String type = p.currentName(); + Column result = switch (type) { case "integer" -> parseIntColumn(); case "keyword" -> parseKeywordColumn(); case "long" -> parseLongColumn(); case "double" -> parseDoubleColumn(); default -> throw new XContentParseException(p.getTokenLocation(), "unsupported type [" + type + "]"); }; + if (p.nextToken() != XContentParser.Token.END_OBJECT) { + result.close(); + throw new XContentParseException(p.getTokenLocation(), "expected " + XContentParser.Token.END_OBJECT); + } + return result; } private Column parseKeywordColumn() throws IOException { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java index b78958152b170..ab0bc114a2765 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java @@ -192,7 +192,7 @@ public void testTablesKeyword() throws IOException { String json = """ { "query": "ROW x = 1", - "tables": {"a": {"c:keyword": ["a", "b", null, 1, 2.0, ["c", "d"], false]}} + "tables": {"a": {"c": {"keyword": ["a", "b", null, 1, 2.0, ["c", "d"], false]}}} } """; EsqlQueryRequest request = parseEsqlQueryRequest(json, randomBoolean()); @@ -223,7 +223,7 @@ public void testTablesInteger() throws IOException { String json = """ { "query": "ROW x = 1", - "tables": {"a": {"c:integer": [1, 2, "3", null, [5, 6]]}} + "tables": {"a": {"c": {"integer": [1, 2, "3", null, [5, 6]]}}} } """; @@ -251,7 +251,7 @@ public void testTablesLong() throws IOException { String json = """ { "query": "ROW x = 1", - "tables": {"a": {"c:long": [1, 2, "3", null, [5, 6]]}} + "tables": {"a": {"c": {"long": [1, 2, "3", null, [5, 6]]}}} } """; @@ -279,7 +279,7 @@ public void testTablesDouble() throws IOException { String json = """ { "query": "ROW x = 1", - "tables": {"a": {"c:double": [1.1, 2, "3.1415", null, [5.1, "-6"]]}} + "tables": {"a": {"c": {"double": [1.1, 2, "3.1415", null, [5.1, "-6"]]}}} } """; @@ -309,16 +309,16 @@ public void testManyTables() throws IOException { "query": "ROW x = 1", "tables": { "t1": { - "a:long": [1], - "b:long": [1], - "c:keyword": [1], - "d:long": [1] + "a": {"long": [1]}, + "b": {"long": [1]}, + "c": {"keyword": [1]}, + "d": {"long": [1]} }, "t2": { - "a:long": [1], - "b:integer": [1], - "c:long": [1], - "d:long": [1] + "a": {"long": [1]}, + "b": {"integer": [1]}, + "c": {"long": [1]}, + "d": {"long": [1]} } } } diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/150_lookup.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/150_lookup.yml index dcffca2f28fb0..5f76954e57c89 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/150_lookup.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/150_lookup.yml @@ -38,7 +38,7 @@ basic: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -48,8 +48,8 @@ basic: columnar: true tables: colors: - "color:keyword": ["red", "green", "blue"] - "rgb:integer": [16711680, 65280, 255] + color: { keyword: ["red", "green", "blue"] } + rgb: { integer: [16711680, 65280, 255] } - match: {columns.0.name: "color"} - match: {columns.0.type: "keyword"} @@ -66,7 +66,7 @@ read multivalue keyword: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -76,11 +76,12 @@ read multivalue keyword: columnar: true tables: color_associations: - "color:keyword": ["red", "green", "blue"] - "association:keyword": - - ["love", "passion", "blood", "happiness"] - - ["nature", "healing", "health", "youth"] - - ["serenity", "wisdom", "ocean", "sky"] + color: {keyword: ["red", "green", "blue"] } + association: + keyword: + - ["love", "passion", "blood", "happiness"] + - ["nature", "healing", "health", "youth"] + - ["serenity", "wisdom", "ocean", "sky"] - match: {columns.0.name: "color"} - match: {columns.0.type: "keyword"} @@ -97,7 +98,7 @@ keyword matches text: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -125,8 +126,8 @@ keyword matches text: columnar: true tables: colors: - "color:keyword": ["red", "green", "blue"] - "rgb:integer": [16711680, 65280, 255] + color: { keyword: ["red", "green", "blue"] } + rgb: { integer: [16711680, 65280, 255] } - match: {columns.0.name: "color"} - match: {columns.0.type: "text"} @@ -135,28 +136,6 @@ keyword matches text: - match: {values.0: ["red"]} - match: {values.1: [16711680]} ---- -duplicate column names in table: - - requires: - test_runner_features: [capabilities] - capabilities: - - method: POST - path: /_query - parameters: [] - capabilities: [lookup_command] - reason: "uses LOOKUP" - - - do: - catch: /duplicate column name \[color\]/ - esql.query: - body: - query: 'FROM test | LOOKUP colors ON color | SORT time | KEEP color, rgb | LIMIT 2' - columnar: true - tables: - colors: - "color:keyword": ["red", "green", "blue"] - "color:integer": [16711680, 65280, 255] - --- duplicate keys: - requires: @@ -165,7 +144,7 @@ duplicate keys: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -177,8 +156,8 @@ duplicate keys: columnar: true tables: colors: - "color:keyword": ["red", "red", "blue"] - "rgb:integer": [16711680, 65280, 255] + color: {keyword: ["red", "red", "blue"] } + rgb: {integer: [16711680, 65280, 255] } --- multivalued keys: @@ -188,7 +167,7 @@ multivalued keys: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -200,8 +179,8 @@ multivalued keys: columnar: true tables: colors: - "color:keyword": [["red", "blue"], "white", "blue"] - "rgb:integer": [16711680, 65280, 255] + color: { keyword: [["red", "blue"], "white", "blue"] } + rgb: { integer: [16711680, 65280, 255] } --- index named lookup still works: @@ -230,7 +209,7 @@ on function: - method: POST path: /_query parameters: [] - capabilities: [lookup_command] + capabilities: [lookup_command, tables_types] reason: "uses LOOKUP" - do: @@ -241,5 +220,5 @@ on function: columnar: true tables: colors: - "color:keyword": ["red", "green", "blue"] - "rgb:integer": [16711680, 65280, 255] + color: { keyword: ["red", "green", "blue"] } + rgb: { integer: [16711680, 65280, 255] } From c888e5f4cda2276ef050b354890899c202af5f88 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 11 Jun 2024 09:27:22 -0400 Subject: [PATCH 11/18] ESQL: Run LOOKUP docs test only in SNAPSHOT (#109493) LOOKUP is only registered on SNAPSHOT builds. closes #109478 --- docs/build.gradle | 9 +++++++++ docs/reference/esql/processing-commands/lookup.asciidoc | 2 +- muted-tests.yml | 3 --- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/build.gradle b/docs/build.gradle index 7bffba0a1957b..e5b8f8d8622ce 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -36,6 +36,15 @@ ext.docsFileTree = fileTree(projectDir) { } } +tasks.named("yamlRestTest") { + if (BuildParams.isSnapshotBuild() == false) { + // LOOKUP is not available in snapshots + systemProperty 'tests.rest.blacklist', [ + "reference/esql/processing-commands/lookup/esql-lookup-example" + ].join(',') + } +} + /* List of files that have snippets that will not work until platinum tests can occur ... */ tasks.named("buildRestTests").configure { getExpectedUnconvertedCandidates().addAll( diff --git a/docs/reference/esql/processing-commands/lookup.asciidoc b/docs/reference/esql/processing-commands/lookup.asciidoc index 88f7570f753ca..1944d243968a8 100644 --- a/docs/reference/esql/processing-commands/lookup.asciidoc +++ b/docs/reference/esql/processing-commands/lookup.asciidoc @@ -27,7 +27,7 @@ adding the other fields from the `table` to the output. *Examples* // tag::examples[] -[source,console] +[source,console,id=esql-lookup-example] ---- POST /_query?format=txt { diff --git a/muted-tests.yml b/muted-tests.yml index 706a59882a20e..4f4d6da837a82 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -59,9 +59,6 @@ tests: - class: org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvAppendTests method: testEvaluateBlockWithoutNulls {TestCase=, } issue: https://github.com/elastic/elasticsearch/issues/109409 -- class: "org.elasticsearch.smoketest.DocsClientYamlTestSuiteIT" - issue: "https://github.com/elastic/elasticsearch/issues/109478" - method: "test {yaml=reference/esql/processing-commands/lookup/line_31}" - class: DenseVectorMappingUpdateIT issue: "https://github.com/elastic/elasticsearch/issues/109571" - class: "org.elasticsearch.compute.lucene.TimeSeriesSortedSourceOperatorTests" From dda08b3f3b749b440a0b9f50be58ec7e39594163 Mon Sep 17 00:00:00 2001 From: David Kyle Date: Tue, 11 Jun 2024 14:37:57 +0100 Subject: [PATCH 12/18] [ML] Log when a model deployment is stopped with pending requests (#109570) --- .../inference/pytorch/process/PyTorchResultProcessor.java | 3 +++ .../job/process/AbstractProcessWorkerExecutorService.java | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/pytorch/process/PyTorchResultProcessor.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/pytorch/process/PyTorchResultProcessor.java index 5636762871b23..87fad19ab87fc 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/pytorch/process/PyTorchResultProcessor.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/pytorch/process/PyTorchResultProcessor.java @@ -141,6 +141,9 @@ public void process(PyTorchProcess process) { } private void notifyAndClearPendingResults(ErrorResult errorResult) { + if (pendingResults.size() > 0) { + logger.warn(format("[%s] clearing [%d] requests pending results", modelId, pendingResults.size())); + } pendingResults.forEach( (id, pendingResult) -> pendingResult.listener.onResponse(new PyTorchResult(id, null, null, null, null, null, errorResult)) ); diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/AbstractProcessWorkerExecutorService.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/AbstractProcessWorkerExecutorService.java index dee608e69f5bb..debe6586e453e 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/AbstractProcessWorkerExecutorService.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/AbstractProcessWorkerExecutorService.java @@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import static org.elasticsearch.core.Strings.format; + /** * A worker service that executes runnables sequentially in * a single worker thread. @@ -139,6 +141,10 @@ public synchronized void notifyQueueRunnables() { assert isShutdown() : "Queue runnables should only be drained and notified after the worker is shutdown"; if (queue.isEmpty() == false) { + logger.warn( + format("[%s] notifying [%d] queued requests that have not been processed before shutdown", processName, queue.size()) + ); + List notExecuted = new ArrayList<>(); queue.drainTo(notExecuted); From 74fa55e60328fe28666fb4b3fae5f87da10216d6 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 11 Jun 2024 15:36:53 +0100 Subject: [PATCH 13/18] Replace reroute request builder with test utils (#109496) This mechanism is basically unused in production code, and presents an obstacle to #107984, so this commit replaces it with a test-only ClusterRerouteUtils and replaces its only production use with code that just creates the request directly. --- .../admin/indices/create/ShrinkIndexIT.java | 7 +- .../cluster/SimpleDataNodesIT.java | 3 +- .../allocation/AwarenessAllocationIT.java | 5 +- .../cluster/allocation/ClusterRerouteIT.java | 103 ++++++++++-------- .../allocation/FilteringAllocationIT.java | 5 +- .../cluster/routing/AllocationIdIT.java | 5 +- .../cluster/routing/PrimaryAllocationIT.java | 72 +++++++----- .../cluster/routing/ShardRoutingRoleIT.java | 3 +- .../decider/DiskThresholdDeciderIT.java | 3 +- .../UpdateShardAllocationSettingsIT.java | 7 +- .../discovery/ClusterDisruptionIT.java | 3 +- .../discovery/MasterDisruptionIT.java | 3 +- .../RemoveCorruptedShardDataCommandIT.java | 5 +- .../index/store/CorruptedFileIT.java | 7 +- .../IndexLifecycleActionIT.java | 7 +- .../indices/IndicesLifecycleListenerIT.java | 3 +- .../indices/cluster/ShardLockFailureIT.java | 5 +- .../recovery/IndexPrimaryRelocationIT.java | 5 +- .../indices/recovery/IndexRecoveryIT.java | 11 +- .../state/CloseWhileRelocatingShardsIT.java | 11 +- .../store/IndicesStoreIntegrationIT.java | 7 +- .../elasticsearch/recovery/RelocationIT.java | 20 ++-- .../search/basic/SearchWhileRelocatingIT.java | 3 +- .../search/fieldcaps/FieldCapabilitiesIT.java | 21 ++-- .../SharedClusterSnapshotRestoreIT.java | 3 +- .../reroute/ClusterRerouteRequestBuilder.java | 3 + .../client/internal/ClusterAdminClient.java | 12 ++ .../cluster/RestClusterRerouteAction.java | 7 +- .../AbstractClientHeadersTestCase.java | 10 +- .../snapshots/SnapshotResiliencyTests.java | 25 ++--- .../cluster/reroute/ClusterRerouteUtils.java | 70 ++++++++++++ .../hamcrest/ElasticsearchAssertions.java | 14 ++- .../existence/FrozenExistenceDeciderIT.java | 4 +- .../storage/ReactiveStorageIT.java | 11 +- .../xpack/esql/action/EsqlDisruptionIT.java | 4 +- .../index/engine/frozen/FrozenIndexIT.java | 5 +- .../xpack/shutdown/NodeShutdownTasksIT.java | 3 +- .../slm/SLMSnapshotBlockingIntegTests.java | 3 +- 38 files changed, 326 insertions(+), 172 deletions(-) create mode 100644 test/framework/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteUtils.java diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/ShrinkIndexIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/ShrinkIndexIT.java index 61e5c1bfcc811..6b2c7f0a9580e 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/ShrinkIndexIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/ShrinkIndexIT.java @@ -13,7 +13,8 @@ import org.apache.lucene.search.SortedSetSelector; import org.apache.lucene.search.SortedSetSortField; import org.apache.lucene.util.Constants; -import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; +import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.action.admin.indices.segments.IndexShardSegments; @@ -396,7 +397,9 @@ public void testCreateShrinkIndexFails() throws Exception { refreshClusterInfo(); // kick off a retry and wait until it's done! - ClusterRerouteResponse clusterRerouteResponse = clusterAdmin().prepareReroute().setRetryFailed(true).get(); + final var clusterRerouteResponse = safeGet( + client().execute(TransportClusterRerouteAction.TYPE, new ClusterRerouteRequest().setRetryFailed(true)) + ); long expectedShardSize = clusterRerouteResponse.getState().routingTable().index("target").shard(0).shard(0).getExpectedShardSize(); // we support the expected shard size in the allocator to sum up over the source index shards assertTrue("expected shard size must be set but wasn't: " + expectedShardSize, expectedShardSize > 0); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/SimpleDataNodesIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/SimpleDataNodesIT.java index 770ca21fd6898..8a239f7293e22 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/SimpleDataNodesIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/SimpleDataNodesIT.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.UnavailableShardsException; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.ActiveShardCount; @@ -106,7 +107,7 @@ public void testAutoExpandReplicasAdjustedWhenDataNodeJoins() { internalCluster().startNode(); internalCluster().startNode(); - clusterAdmin().prepareReroute().setRetryFailed(true).get(); + ClusterRerouteUtils.rerouteRetryFailed(client()); } } diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/AwarenessAllocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/AwarenessAllocationIT.java index e6ea4823e86f0..71418cb83debe 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/AwarenessAllocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/AwarenessAllocationIT.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetadata.State; import org.elasticsearch.cluster.routing.IndexRoutingTable; @@ -184,7 +185,7 @@ public void testAwarenessZonesIncrementalNodes() { .setWaitForNodes("3") .get(); assertThat(health.isTimedOut(), equalTo(false)); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); health = clusterAdmin().prepareHealth() .setIndices("test") .setWaitForEvents(Priority.LANGUID) @@ -210,7 +211,7 @@ public void testAwarenessZonesIncrementalNodes() { .setWaitForNodes("4") .get(); assertThat(health.isTimedOut(), equalTo(false)); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); health = clusterAdmin().prepareHealth() .setIndices("test") .setWaitForEvents(Priority.LANGUID) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java index bacff31b480ec..5f75b62cabb69 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java @@ -11,7 +11,9 @@ import org.apache.logging.log4j.Level; import org.apache.lucene.tests.util.LuceneTestCase; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.WriteRequest.RefreshPolicy; @@ -99,12 +101,14 @@ private void rerouteWithCommands(Settings commonSettings) throws Exception { assertThat(state.getRoutingNodes().unassigned().size(), equalTo(2)); logger.info("--> explicitly allocate shard 1, *under dry_run*"); - state = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) - .setDryRun(true) - .get() - .getState(); + state = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()) + .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + .dryRun(true) + ) + ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); assertThat( state.getRoutingNodes().node(state.nodes().resolveNode(node_1).getId()).iterator().next().state(), @@ -116,11 +120,12 @@ private void rerouteWithCommands(Settings commonSettings) throws Exception { assertThat(state.getRoutingNodes().unassigned().size(), equalTo(2)); logger.info("--> explicitly allocate shard 1, actually allocating, no dry run"); - state = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) - .get() - .getState(); + state = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + ) + ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); assertThat( state.getRoutingNodes().node(state.nodes().resolveNode(node_1).getId()).iterator().next().state(), @@ -143,11 +148,12 @@ private void rerouteWithCommands(Settings commonSettings) throws Exception { ); logger.info("--> move shard 1 primary from node1 to node2"); - state = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .add(new MoveAllocationCommand("test", 0, node_1, node_2)) - .get() - .getState(); + state = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()).add(new MoveAllocationCommand("test", 0, node_1, node_2)) + ) + ).getState(); assertThat( state.getRoutingNodes().node(state.nodes().resolveNode(node_1).getId()).iterator().next().state(), @@ -250,11 +256,12 @@ private void rerouteWithAllocateLocalGateway(Settings commonSettings) throws Exc assertThat(state.getRoutingNodes().unassigned().size(), equalTo(2)); logger.info("--> explicitly allocate shard 1, actually allocating, no dry run"); - state = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) - .get() - .getState(); + state = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + ) + ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); assertThat( state.getRoutingNodes().node(state.nodes().resolveNode(node_1).getId()).iterator().next().state(), @@ -295,17 +302,18 @@ private void rerouteWithAllocateLocalGateway(Settings commonSettings) throws Exc internalCluster().startNode(commonSettings); // wait a bit for the cluster to realize that the shard is not there... // TODO can we get around this? the cluster is RED, so what do we wait for? - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); assertThat( clusterAdmin().prepareHealth().setIndices("test").setWaitForNodes("2").get().getStatus(), equalTo(ClusterHealthStatus.RED) ); logger.info("--> explicitly allocate primary"); - state = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) - .get() - .getState(); + state = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + ) + ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); assertThat( state.getRoutingNodes().node(state.nodes().resolveNode(node_1).getId()).iterator().next().state(), @@ -350,7 +358,9 @@ public void testRerouteExplain() { logger.info("--> try to move the shard from node1 to node2"); MoveAllocationCommand cmd = new MoveAllocationCommand("test", 0, node_1, node_2); - ClusterRerouteResponse resp = clusterAdmin().prepareReroute().add(cmd).setExplain(true).get(); + ClusterRerouteResponse resp = safeGet( + client().execute(TransportClusterRerouteAction.TYPE, new ClusterRerouteRequest().add(cmd).explain(true)) + ); RoutingExplanations e = resp.getExplanations(); assertThat(e.explanations().size(), equalTo(1)); RerouteExplanation explanation = e.explanations().get(0); @@ -398,11 +408,12 @@ public void testMessageLogging() { ); AllocationCommand dryRunAllocation = new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeName1, true); - ClusterRerouteResponse dryRunResponse = clusterAdmin().prepareReroute() - .setExplain(randomBoolean()) - .setDryRun(true) - .add(dryRunAllocation) - .get(); + ClusterRerouteResponse dryRunResponse = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(randomBoolean()).dryRun(true).add(dryRunAllocation) + ) + ); // during a dry run, messages exist but are not logged or exposed assertThat(dryRunResponse.getExplanations().getYesDecisionMessages(), hasSize(1)); @@ -431,11 +442,14 @@ public void testMessageLogging() { AllocationCommand yesDecisionAllocation = new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeName1, true); AllocationCommand noDecisionAllocation = new AllocateEmptyPrimaryAllocationCommand("noexist", 1, nodeName2, true); - ClusterRerouteResponse response = clusterAdmin().prepareReroute() - .setExplain(true) // so we get a NO decision back rather than an exception - .add(yesDecisionAllocation) - .add(noDecisionAllocation) - .get(); + ClusterRerouteResponse response = safeGet( + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().explain(true) // so we get a NO decision back rather than an exception + .add(yesDecisionAllocation) + .add(noDecisionAllocation) + ) + ); assertThat(response.getExplanations().getYesDecisionMessages(), hasSize(1)); assertThat(response.getExplanations().getYesDecisionMessages().get(0), containsString("allocated an empty primary")); @@ -482,9 +496,9 @@ public void testClusterRerouteWithBlocks() { )) { try { enableIndexBlock("test-blocks", blockSetting); - assertAcked( - clusterAdmin().prepareReroute() - .add(new MoveAllocationCommand("test-blocks", 0, nodesIds.get(toggle % 2), nodesIds.get(++toggle % 2))) + ClusterRerouteUtils.reroute( + client(), + new MoveAllocationCommand("test-blocks", 0, nodesIds.get(toggle % 2), nodesIds.get(++toggle % 2)) ); ClusterHealthResponse healthResponse = clusterAdmin().prepareHealth() @@ -502,8 +516,11 @@ public void testClusterRerouteWithBlocks() { try { setClusterReadOnly(true); assertBlocked( - clusterAdmin().prepareReroute() - .add(new MoveAllocationCommand("test-blocks", 1, nodesIds.get(toggle % 2), nodesIds.get(++toggle % 2))) + null, + ClusterRerouteUtils.expectRerouteFailure( + client(), + new MoveAllocationCommand("test-blocks", 1, nodesIds.get(toggle % 2), nodesIds.get(++toggle % 2)) + ) ); } finally { setClusterReadOnly(false); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/FilteringAllocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/FilteringAllocationIT.java index ae79c388aa104..5f54b32ab4a14 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/FilteringAllocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/FilteringAllocationIT.java @@ -8,6 +8,7 @@ package org.elasticsearch.cluster.allocation; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.metadata.AutoExpandReplicas; @@ -160,7 +161,7 @@ public void testDisablingAllocationFiltering() { } logger.info("--> remove index from the first node"); updateIndexSettings(Settings.builder().put("index.routing.allocation.exclude._name", node_0), "test"); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); ensureGreen("test"); logger.info("--> verify all shards are allocated on node_1 now"); @@ -175,7 +176,7 @@ public void testDisablingAllocationFiltering() { logger.info("--> disable allocation filtering "); updateIndexSettings(Settings.builder().put("index.routing.allocation.exclude._name", ""), "test"); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); ensureGreen("test"); logger.info("--> verify that there are shards allocated on both nodes now"); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/AllocationIdIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/AllocationIdIT.java index a25de555ce267..8cee57ee34b89 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/AllocationIdIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/AllocationIdIT.java @@ -10,6 +10,7 @@ import org.elasticsearch.action.admin.cluster.allocation.ClusterAllocationExplanationUtils; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.cluster.ClusterState; @@ -106,7 +107,7 @@ public void testFailedRecoveryOnAllocateStalePrimaryRequiresAnotherAllocateStale checkNoValidShardCopy(indexName, shardId); // allocate stale primary - client(node1).admin().cluster().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(indexName, 0, node1, true)).get(); + ClusterRerouteUtils.reroute(client(node1), new AllocateStalePrimaryAllocationCommand(indexName, 0, node1, true)); // allocation fails due to corruption marker assertBusy(() -> { @@ -127,7 +128,7 @@ public void testFailedRecoveryOnAllocateStalePrimaryRequiresAnotherAllocateStale checkNoValidShardCopy(indexName, shardId); // no any valid shard is there; have to invoke AllocateStalePrimary again - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(indexName, 0, node1, true)).get(); + ClusterRerouteUtils.reroute(client(), new AllocateStalePrimaryAllocationCommand(indexName, 0, node1, true)); ensureYellow(indexName); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java index 72594fef8c6ee..db84f2a0a34d0 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java @@ -9,7 +9,9 @@ package org.elasticsearch.cluster.routing; import org.elasticsearch.action.DocWriteResponse; -import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequestBuilder; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; +import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest; import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresResponse; import org.elasticsearch.action.admin.indices.shards.TransportIndicesShardStoresAction; @@ -156,12 +158,13 @@ private Settings createStaleReplicaScenario(String master) throws Exception { logger.info("--> check that old primary shard does not get promoted to primary again"); // kick reroute and wait for all shard states to be fetched - client(master).admin().cluster().prepareReroute().get(); + ClusterRerouteUtils.reroute(client(master)); assertBusy( () -> assertThat(internalCluster().getInstance(GatewayAllocator.class, master).getNumberOfInFlightFetches(), equalTo(0)) ); // kick reroute a second time and check that all shards are unassigned - assertThat(client(master).admin().cluster().prepareReroute().get().getState().getRoutingNodes().unassigned().size(), equalTo(2)); + ClusterRerouteUtils.reroute(client(master)); + assertThat(client(master).admin().cluster().prepareState().get().getState().getRoutingNodes().unassigned().size(), equalTo(2)); return inSyncDataPathSettings; } @@ -207,11 +210,16 @@ public void testFailedAllocationOfStalePrimaryToDataNodeWithNoData() throws Exce ); logger.info("--> force allocation of stale copy to node that does not have shard copy"); - Throwable iae = expectThrows( - IllegalArgumentException.class, - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand("test", 0, dataNodeWithNoShardCopy, true)) + assertEquals( + "No data for shard [0] of index [test] found on any node", + asInstanceOf( + IllegalArgumentException.class, + ClusterRerouteUtils.expectRerouteFailure( + client(), + new AllocateStalePrimaryAllocationCommand("test", 0, dataNodeWithNoShardCopy, true) + ) + ).getMessage() ); - assertThat(iae.getMessage(), equalTo("No data for shard [0] of index [test] found on any node")); logger.info("--> wait until shard is failed and becomes unassigned again"); assertTrue( @@ -252,16 +260,16 @@ public void testForceStaleReplicaToBePromotedToPrimary() throws Exception { TransportIndicesShardStoresAction.TYPE, new IndicesShardStoresRequest(idxName) ).get().getStoreStatuses().get(idxName); - ClusterRerouteRequestBuilder rerouteBuilder = clusterAdmin().prepareReroute(); + final var rerouteRequest = new ClusterRerouteRequest(); for (Map.Entry> shardStoreStatuses : storeStatuses.entrySet()) { int shardId = shardStoreStatuses.getKey(); IndicesShardStoresResponse.StoreStatus storeStatus = randomFrom(shardStoreStatuses.getValue()); logger.info("--> adding allocation command for shard {}", shardId); // force allocation based on node id if (useStaleReplica) { - rerouteBuilder.add(new AllocateStalePrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true)); + rerouteRequest.add(new AllocateStalePrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true)); } else { - rerouteBuilder.add(new AllocateEmptyPrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true)); + rerouteRequest.add(new AllocateEmptyPrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true)); } } @@ -280,7 +288,7 @@ public void testForceStaleReplicaToBePromotedToPrimary() throws Exception { final ClusterService clusterService = internalCluster().getInstance(ClusterService.class, master); clusterService.addListener(clusterStateListener); - rerouteBuilder.get(); + assertAcked(safeGet(client().execute(TransportClusterRerouteAction.TYPE, rerouteRequest))); assertTrue(clusterStateChangeLatch.await(30, TimeUnit.SECONDS)); clusterService.removeListener(clusterStateListener); @@ -341,13 +349,16 @@ public void testForceStaleReplicaToBePromotedToPrimaryOnWrongNode() throws Excep .forEach(status -> nodeNames.remove(status.getNode().getName())); assertThat(nodeNames, hasSize(1)); final String nodeWithoutData = nodeNames.get(0); - Throwable iae = expectThrows( - IllegalArgumentException.class, - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(idxName, shardId, nodeWithoutData, true)) - ); - assertThat( - iae.getMessage(), - equalTo("No data for shard [" + shardId + "] of index [" + idxName + "] found on node [" + nodeWithoutData + ']') + + assertEquals( + "No data for shard [" + shardId + "] of index [" + idxName + "] found on node [" + nodeWithoutData + ']', + asInstanceOf( + IllegalArgumentException.class, + ClusterRerouteUtils.expectRerouteFailure( + client(), + new AllocateStalePrimaryAllocationCommand(idxName, shardId, nodeWithoutData, true) + ) + ).getMessage() ); } @@ -359,22 +370,29 @@ public void testForceStaleReplicaToBePromotedForGreenIndex() { ensureGreen(); final String nodeWithoutData = randomFrom(dataNodes); final int shardId = 0; - IllegalArgumentException iae = expectThrows( - IllegalArgumentException.class, - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(idxName, shardId, nodeWithoutData, true)) + assertEquals( + "[allocate_stale_primary] primary [" + idxName + "][" + shardId + "] is already assigned", + asInstanceOf( + IllegalArgumentException.class, + ClusterRerouteUtils.expectRerouteFailure( + client(), + new AllocateStalePrimaryAllocationCommand(idxName, shardId, nodeWithoutData, true) + ) + ).getMessage() ); - assertThat(iae.getMessage(), equalTo("[allocate_stale_primary] primary [" + idxName + "][" + shardId + "] is already assigned")); } public void testForceStaleReplicaToBePromotedForMissingIndex() { internalCluster().startMasterOnlyNode(Settings.EMPTY); final String dataNode = internalCluster().startDataOnlyNode(); final String idxName = "test"; - IndexNotFoundException ex = expectThrows( - IndexNotFoundException.class, - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(idxName, 0, dataNode, true)) + assertEquals( + idxName, + asInstanceOf( + IndexNotFoundException.class, + ClusterRerouteUtils.expectRerouteFailure(client(), new AllocateStalePrimaryAllocationCommand(idxName, 0, dataNode, true)) + ).getIndex().getName() ); - assertThat(ex.getIndex().getName(), equalTo(idxName)); } public void testForcePrimaryShardIfAllocationDecidersSayNoAfterIndexCreation() throws ExecutionException, InterruptedException { @@ -386,7 +404,7 @@ public void testForcePrimaryShardIfAllocationDecidersSayNoAfterIndexCreation() t assertThat(clusterAdmin().prepareState().get().getState().getRoutingTable().shardRoutingTable("test", 0).assignedShards(), empty()); - clusterAdmin().prepareReroute().add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node, true)).get(); + ClusterRerouteUtils.reroute(client(), new AllocateEmptyPrimaryAllocationCommand("test", 0, node, true)); ensureGreen("test"); } diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/ShardRoutingRoleIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/ShardRoutingRoleIT.java index 76311387115d2..bb9324dd7d10c 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/ShardRoutingRoleIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/ShardRoutingRoleIT.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.shards.ClusterSearchShardsGroup; import org.elasticsearch.action.admin.indices.refresh.TransportUnpromotableShardRefreshAction; import org.elasticsearch.action.search.ClosePointInTimeRequest; @@ -422,7 +423,7 @@ public void testPromotion() { updateIndexSettings(Settings.builder().put(IndexMetadata.INDEX_ROUTING_REQUIRE_GROUP_PREFIX + "._name", "not-a-node"), "test"); AllocationCommand cancelPrimaryCommand; while ((cancelPrimaryCommand = getCancelPrimaryCommand()) != null) { - clusterAdmin().prepareReroute().add(cancelPrimaryCommand).get(); + ClusterRerouteUtils.reroute(client(), cancelPrimaryCommand); } } finally { masterClusterService.removeListener(routingTableWatcher); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderIT.java index 8499bc8aef4ad..16be816b69bc4 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderIT.java @@ -8,6 +8,7 @@ package org.elasticsearch.cluster.routing.allocation.decider; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; import org.elasticsearch.action.admin.indices.stats.ShardStats; @@ -314,7 +315,7 @@ private void refreshDiskUsage() { .values() .stream() .allMatch(e -> e.freeBytes() > WATERMARK_BYTES)) { - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); } assertFalse( diff --git a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/UpdateShardAllocationSettingsIT.java b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/UpdateShardAllocationSettingsIT.java index da1156953e26c..921ed3265f1b6 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/UpdateShardAllocationSettingsIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/UpdateShardAllocationSettingsIT.java @@ -7,6 +7,7 @@ */ package org.elasticsearch.cluster.routing.allocation.decider; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.routing.ShardRoutingState; import org.elasticsearch.common.settings.Settings; @@ -50,7 +51,7 @@ public void testEnableRebalance() { .put(EnableAllocationDecider.INDEX_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), EnableAllocationDecider.Rebalance.NONE), "test" ); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); ensureGreen(); assertAllShardsOnNodes("test", firstNode); assertAllShardsOnNodes("test_1", firstNode); @@ -65,7 +66,7 @@ public void testEnableRebalance() { "test" ); logger.info("--> balance index [test]"); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); ensureGreen("test"); Set test = assertAllShardsOnNodes("test", firstNode, secondNode); assertThat("index: [test] expected to be rebalanced on both nodes", test.size(), equalTo(2)); @@ -80,7 +81,7 @@ public void testEnableRebalance() { ) ); logger.info("--> balance index [test_1]"); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); ensureGreen("test_1"); Set test_1 = assertAllShardsOnNodes("test_1", firstNode, secondNode); assertThat("index: [test_1] expected to be rebalanced on both nodes", test_1.size(), equalTo(2)); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/discovery/ClusterDisruptionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/discovery/ClusterDisruptionIT.java index cd9adea500dbd..a0fa63aa58ab5 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/discovery/ClusterDisruptionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/discovery/ClusterDisruptionIT.java @@ -13,6 +13,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.NoShardAvailableActionException; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.support.PlainActionFuture; @@ -233,7 +234,7 @@ public void testAckedIndexing() throws Exception { // is the super-connected node and recovery source and target are on opposite sides of the bridge if (disruptionScheme instanceof NetworkDisruption networkDisruption && networkDisruption.getDisruptedLinks() instanceof Bridge) { - assertBusy(() -> assertAcked(clusterAdmin().prepareReroute().setRetryFailed(true))); + assertBusy(() -> ClusterRerouteUtils.rerouteRetryFailed(client())); } ensureGreen("test"); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/discovery/MasterDisruptionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/discovery/MasterDisruptionIT.java index af254d42ec3ee..3e7e4d47e7a23 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/discovery/MasterDisruptionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/discovery/MasterDisruptionIT.java @@ -8,6 +8,7 @@ package org.elasticsearch.discovery; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.bulk.BulkRequestBuilder; @@ -116,7 +117,7 @@ public void testIsolateMasterAndVerifyClusterStateConsensus() throws Exception { logger.info("issue a reroute"); // trigger a reroute now, instead of waiting for the background reroute of RerouteService - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); // and wait for it to finish and for the cluster to stabilize ensureGreen("test"); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommandIT.java b/server/src/internalClusterTest/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommandIT.java index ef4616fdd0b40..bdfe629f4bab0 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommandIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommandIT.java @@ -20,6 +20,7 @@ import org.apache.lucene.store.NativeFSLockFactory; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.admin.indices.stats.ShardStats; @@ -219,7 +220,7 @@ public Settings onNodeStopped(String nodeName) throws Exception { ); }); - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(indexName, 0, nodeId, true)).get(); + ClusterRerouteUtils.reroute(client(), new AllocateStalePrimaryAllocationCommand(indexName, 0, nodeId, true)); assertBusy(() -> { final var explanation = getClusterAllocationExplanation(client(), indexName, 0, true); @@ -373,7 +374,7 @@ public Settings onNodeStopped(String nodeName) throws Exception { ); }); - clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand(indexName, 0, primaryNodeId, true)).get(); + ClusterRerouteUtils.reroute(client(), new AllocateStalePrimaryAllocationCommand(indexName, 0, primaryNodeId, true)); assertBusy(() -> { final var explanation = getClusterAllocationExplanation(client(), indexName, 0, true); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/index/store/CorruptedFileIT.java b/server/src/internalClusterTest/java/org/elasticsearch/index/store/CorruptedFileIT.java index 7e3df8d8e1cbc..2fed0a45032a9 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/index/store/CorruptedFileIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/index/store/CorruptedFileIT.java @@ -19,6 +19,7 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest; @@ -284,7 +285,7 @@ public void testCorruptPrimaryNoReplica() throws ExecutionException, Interrupted * we corrupted the primary shard - now lets make sure we never recover from it successfully */ setReplicaCount(1, "test"); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); boolean didClusterTurnRed = waitUntil(() -> { ClusterHealthStatus test = clusterAdmin().health(new ClusterHealthRequest("test")).actionGet().getStatus(); @@ -368,7 +369,7 @@ public void testCorruptionOnNetworkLayerFinalizingRecovery() throws InterruptedE .put("index.routing.allocation.include._name", primariesNode.getName() + "," + unluckyNode.getName()), "test" ); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); hasCorrupted.await(); corrupt.set(false); ensureGreen(); @@ -493,7 +494,7 @@ public void onTimeout(TimeValue timeout) { .put("index.routing.allocation.exclude._name", unluckyNode.getName()), "test" ); - clusterAdmin().prepareReroute().setRetryFailed(true).get(); + ClusterRerouteUtils.rerouteRetryFailed(client()); ensureGreen("test"); assertThatAllShards("test", shard -> { assertThat(shard.primaryShard().currentNodeId(), not(equalTo(unluckyNode.getId()))); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java index 28a5ad9c29126..5c4cdc8cde851 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java @@ -10,6 +10,7 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; @@ -79,7 +80,7 @@ public void testIndexLifecycleActionsWith11Shards1Backup() throws Exception { final String node2 = getLocalNodeId(server_2); // explicitly call reroute, so shards will get relocated to the new node (we delay it in ES in case other nodes join) - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); clusterHealth = clusterAdmin().health( new ClusterHealthRequest(new String[] {}).waitForGreenStatus().waitForNodes("2").waitForNoRelocatingShards(true) @@ -120,7 +121,7 @@ public void testIndexLifecycleActionsWith11Shards1Backup() throws Exception { final String node3 = getLocalNodeId(server_3); // explicitly call reroute, so shards will get relocated to the new node (we delay it in ES in case other nodes join) - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); clusterHealth = clusterAdmin().prepareHealth() .setWaitForGreenStatus() @@ -174,7 +175,7 @@ public void testIndexLifecycleActionsWith11Shards1Backup() throws Exception { assertThat(clusterHealth.isTimedOut(), equalTo(false)); assertThat(clusterHealth.getStatus(), equalTo(ClusterHealthStatus.GREEN)); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); clusterHealth = clusterAdmin().prepareHealth() .setWaitForGreenStatus() diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/IndicesLifecycleListenerIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/IndicesLifecycleListenerIT.java index d5cbb215781b7..b224d70eed8f8 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/IndicesLifecycleListenerIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/IndicesLifecycleListenerIT.java @@ -8,6 +8,7 @@ package org.elasticsearch.indices; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.cluster.routing.ShardRoutingState; import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand; @@ -115,7 +116,7 @@ public void beforeIndexCreated(Index index, Settings indexSettings) { throw new RuntimeException("FAIL"); } }); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand("index1", 0, node1, node2)).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("index1", 0, node1, node2)); ensureGreen("index1"); var state = clusterAdmin().prepareState().get().getState(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/cluster/ShardLockFailureIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/cluster/ShardLockFailureIT.java index 874ba7b42690c..28e89f4590557 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/cluster/ShardLockFailureIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/cluster/ShardLockFailureIT.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LogEvent; import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.routing.allocation.decider.MaxRetryAllocationDecider; @@ -28,8 +29,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; - public class ShardLockFailureIT extends ESIntegTestCase { @TestLogging(reason = "checking DEBUG logs from ICSS", value = "org.elasticsearch.indices.cluster.IndicesClusterStateService:DEBUG") @@ -165,7 +164,7 @@ public void testShardLockTimeout() throws Exception { assertEquals(1, clusterHealthResponse.getUnassignedShards()); } - assertAcked(clusterAdmin().prepareReroute().setRetryFailed(true)); + ClusterRerouteUtils.rerouteRetryFailed(client()); ensureGreen(indexName); } } diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java index 779072272e59a..a9e06fe438c41 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.Level; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -63,9 +64,7 @@ public void run() { relocationTarget = randomFrom(dataNodes); } logger.info("--> [iteration {}] relocating from {} to {} ", i, relocationSource.getName(), relocationTarget.getName()); - clusterAdmin().prepareReroute() - .add(new MoveAllocationCommand("test", 0, relocationSource.getId(), relocationTarget.getId())) - .get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, relocationSource.getId(), relocationTarget.getId())); ClusterHealthResponse clusterHealthResponse = clusterAdmin().prepareHealth() .setTimeout(TimeValue.timeValueSeconds(60)) .setWaitForEvents(Priority.LANGUID) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexRecoveryIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexRecoveryIT.java index 23963fe50aa44..14b13addac84f 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexRecoveryIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/recovery/IndexRecoveryIT.java @@ -28,6 +28,7 @@ import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest; @@ -281,7 +282,7 @@ private void unthrottleRecovery() { */ public void startShardRecovery(String sourceNode, String targetNode) throws Exception { logger.info("--> updating cluster settings with moving shard from node `{}` to node `{}`", sourceNode, targetNode); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand(INDEX_NAME, 0, sourceNode, targetNode)).get().getState(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand(INDEX_NAME, 0, sourceNode, targetNode)); logger.info("--> requesting shard recovery"); indicesAdmin().prepareRecoveries(INDEX_NAME).get(); @@ -553,7 +554,7 @@ public void testRerouteRecovery() throws Exception { throttleRecovery10Seconds(shardSize); logger.info("--> move shard from: {} to: {}", nodeA, nodeB); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand(INDEX_NAME, 0, nodeA, nodeB)).get().getState(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand(INDEX_NAME, 0, nodeA, nodeB)); logger.info("--> waiting for recovery to start both on source and target"); final Index index = resolveIndex(INDEX_NAME); @@ -639,7 +640,7 @@ public void testRerouteRecovery() throws Exception { throttleRecovery10Seconds(shardSize); logger.info("--> move replica shard from: {} to: {}", nodeA, nodeC); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand(INDEX_NAME, 0, nodeA, nodeC)).get().getState(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand(INDEX_NAME, 0, nodeA, nodeC)); response = indicesAdmin().prepareRecoveries(INDEX_NAME).get(); recoveryStates = response.shardRecoveryStates().get(INDEX_NAME); @@ -1643,7 +1644,7 @@ public void testAllocateEmptyPrimaryResetsGlobalCheckpoint() throws Exception { internalCluster().stopRandomDataNode(); internalCluster().stopRandomDataNode(); final String nodeWithoutData = internalCluster().startDataOnlyNode(); - assertAcked(clusterAdmin().prepareReroute().add(new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeWithoutData, true))); + ClusterRerouteUtils.reroute(client(), new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeWithoutData, true)); internalCluster().startDataOnlyNode(randomNodeDataPathSettings); ensureGreen(); for (ShardStats shardStats : indicesAdmin().prepareStats(indexName).get().getIndex(indexName).getShards()) { @@ -1712,7 +1713,7 @@ public void testCancelRecoveryWithAutoExpandReplicas() throws Exception { ); internalCluster().startNode(); internalCluster().startNode(); - clusterAdmin().prepareReroute().setRetryFailed(true).get(); + ClusterRerouteUtils.rerouteRetryFailed(client()); assertAcked(indicesAdmin().prepareDelete("test")); // cancel recoveries assertBusy(() -> { for (PeerRecoverySourceService recoveryService : internalCluster().getDataNodeInstances(PeerRecoverySourceService.class)) { diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/state/CloseWhileRelocatingShardsIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/state/CloseWhileRelocatingShardsIT.java index b66a0b0f3be44..b160834d675d9 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/state/CloseWhileRelocatingShardsIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/state/CloseWhileRelocatingShardsIT.java @@ -7,13 +7,13 @@ */ package org.elasticsearch.indices.state; -import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; -import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands; +import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand; import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand; import org.elasticsearch.cluster.routing.allocation.decider.ConcurrentRebalanceAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider; @@ -125,7 +125,7 @@ public void testCloseWhileRelocatingShards() throws Exception { final CountDownLatch release = new CountDownLatch(indices.length); // relocate one shard for every index to be closed - final AllocationCommands commands = new AllocationCommands(); + final var commands = new ArrayList(); for (final String index : indices) { final NumShards numShards = getNumShards(index); final int shardId = numShards.numPrimaries == 1 ? 0 : randomIntBetween(0, numShards.numPrimaries - 1); @@ -146,8 +146,7 @@ public void testCloseWhileRelocatingShards() throws Exception { } // Build the list of shards for which recoveries will be blocked - final Set blockedShards = commands.commands() - .stream() + final Set blockedShards = commands.stream() .map(c -> (MoveAllocationCommand) c) .map(c -> new ShardId(clusterService.state().metadata().index(c.index()).getIndex(), c.shardId())) .collect(Collectors.toSet()); @@ -185,7 +184,7 @@ public void testCloseWhileRelocatingShards() throws Exception { } } - assertAcked(clusterAdmin().reroute(new ClusterRerouteRequest().commands(commands)).get()); + ClusterRerouteUtils.reroute(client(), commands.toArray(AllocationCommand[]::new)); // start index closing threads final List threads = new ArrayList<>(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/store/IndicesStoreIntegrationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/store/IndicesStoreIntegrationIT.java index 5805eab831230..5eeb07968ce4d 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/store/IndicesStoreIntegrationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/store/IndicesStoreIntegrationIT.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.Logger; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.health.ClusterHealthStatus; @@ -128,7 +129,7 @@ public void testIndexCleanup() throws Exception { logger.info("--> stopping disruption"); disruption.stopDisrupting(); } else { - internalCluster().client().admin().cluster().prepareReroute().add(new MoveAllocationCommand("test", 0, node_1, node_3)).get(); + ClusterRerouteUtils.reroute(internalCluster().client(), new MoveAllocationCommand("test", 0, node_1, node_3)); } clusterHealth = clusterAdmin().prepareHealth().setWaitForNoRelocatingShards(true).get(); assertThat(clusterHealth.isTimedOut(), equalTo(false)); @@ -172,7 +173,7 @@ public void onRequestReceived(long requestId, String action) { } } }); - internalCluster().client().admin().cluster().prepareReroute().add(new MoveAllocationCommand(index, shard, nodeFrom, nodeTo)).get(); + ClusterRerouteUtils.reroute(internalCluster().client(), new MoveAllocationCommand(index, shard, nodeFrom, nodeTo)); logger.info("--> waiting for relocation to start"); beginRelocationLatch.await(); logger.info("--> starting disruption"); @@ -223,7 +224,7 @@ public void testShardCleanupIfShardDeletionAfterRelocationFailedAndIndexDeleted( }); logger.info("--> move shard from {} to {}, and wait for relocation to finish", node_1, node_2); - internalCluster().client().admin().cluster().prepareReroute().add(new MoveAllocationCommand("test", 0, node_1, node_2)).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, node_1, node_2)); shardActiveRequestSent.await(); ClusterHealthResponse clusterHealth = clusterAdmin().prepareHealth().setWaitForNoRelocatingShards(true).get(); assertThat(clusterHealth.isTimedOut(), equalTo(false)); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java index 4c3c05992a449..f0026dfa0a340 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java @@ -13,7 +13,10 @@ import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; +import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.support.WriteRequest; @@ -144,7 +147,7 @@ public void testSimpleRelocationNoIndexing() { assertThat(clusterHealthResponse.isTimedOut(), equalTo(false)); logger.info("--> relocate the shard from node1 to node2"); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand("test", 0, node_1, node_2)).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, node_1, node_2)); clusterHealthResponse = clusterAdmin().prepareHealth() .setWaitForEvents(Priority.LANGUID) @@ -207,7 +210,7 @@ public void testRelocationWhileIndexingRandom() throws Exception { logger.debug("--> Allow indexer to index [{}] documents", numDocs); indexer.continueIndexing(numDocs); logger.info("--> START relocate the shard from {} to {}", nodes[fromNode], nodes[toNode]); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand("test", 0, nodes[fromNode], nodes[toNode])).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, nodes[fromNode], nodes[toNode])); if (rarely()) { logger.debug("--> flushing"); indicesAdmin().prepareFlush().get(); @@ -334,7 +337,7 @@ public void indexShardStateChanged( logger.info("--> START relocate the shard from {} to {}", nodes[fromNode], nodes[toNode]); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand("test", 0, nodes[fromNode], nodes[toNode])).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, nodes[fromNode], nodes[toNode])); logger.debug("--> index [{}] documents", builders1.size()); indexRandom(false, true, builders1); @@ -555,7 +558,7 @@ public void testRelocateWhileWaitingForRefresh() { assertThat(clusterHealthResponse.isTimedOut(), equalTo(false)); logger.info("--> relocate the shard from node1 to node2"); - clusterAdmin().prepareReroute().add(new MoveAllocationCommand("test", 0, node1, node2)).get(); + ClusterRerouteUtils.reroute(client(), new MoveAllocationCommand("test", 0, node1, node2)); clusterHealthResponse = clusterAdmin().prepareHealth() .setWaitForEvents(Priority.LANGUID) @@ -606,9 +609,10 @@ public void testRelocateWhileContinuouslyIndexingAndWaitingForRefresh() throws E assertThat(clusterHealthResponse.isTimedOut(), equalTo(false)); logger.info("--> relocate the shard from node1 to node2"); - ActionFuture relocationListener = clusterAdmin().prepareReroute() - .add(new MoveAllocationCommand("test", 0, node1, node2)) - .execute(); + ActionFuture relocationListener = client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().add(new MoveAllocationCommand("test", 0, node1, node2)) + ); logger.info("--> index 100 docs while relocating"); for (int i = 20; i < 120; i++) { pendingIndexResponses.add( @@ -618,7 +622,7 @@ public void testRelocateWhileContinuouslyIndexingAndWaitingForRefresh() throws E .execute() ); } - relocationListener.actionGet(); + safeGet(relocationListener); clusterHealthResponse = clusterAdmin().prepareHealth() .setWaitForEvents(Priority.LANGUID) .setWaitForNoRelocatingShards(true) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/basic/SearchWhileRelocatingIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/basic/SearchWhileRelocatingIT.java index 03a21210630b7..657158327bf01 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/basic/SearchWhileRelocatingIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/basic/SearchWhileRelocatingIT.java @@ -10,6 +10,7 @@ import org.elasticsearch.action.NoShardAvailableActionException; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.search.SearchPhaseExecutionException; import org.elasticsearch.common.Priority; @@ -118,7 +119,7 @@ public void run() { threads[j].start(); } allowNodes("test", between(1, 3)); - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); stop.set(true); for (int j = 0; j < threads.length; j++) { threads[j].join(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/fieldcaps/FieldCapabilitiesIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/fieldcaps/FieldCapabilitiesIT.java index ae3347dafd55d..9d3ce1c99b553 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/fieldcaps/FieldCapabilitiesIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/fieldcaps/FieldCapabilitiesIT.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.Level; import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.fieldcaps.FieldCapabilities; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesFailure; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest; @@ -549,18 +550,14 @@ private void moveOrCloseShardsOnNodes(String nodeName) throws Exception { if (targetNodes.isEmpty()) { continue; } - - safeGet( - clusterAdmin().prepareReroute() - .add( - new MoveAllocationCommand( - shardId.getIndexName(), - shardId.id(), - indicesService.clusterService().localNode().getId(), - randomFrom(targetNodes) - ) - ) - .execute() + ClusterRerouteUtils.reroute( + client(), + new MoveAllocationCommand( + shardId.getIndexName(), + shardId.id(), + indicesService.clusterService().localNode().getId(), + randomFrom(targetNodes) + ) ); } } diff --git a/server/src/internalClusterTest/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java b/server/src/internalClusterTest/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java index 6e19cf60cf5b9..d625b53785d38 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java @@ -12,6 +12,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; @@ -597,7 +598,7 @@ public void testUnrestorableIndexDuringRestore() throws Exception { Runnable fixupAction = () -> { // remove the shard allocation filtering settings and use the Reroute API to retry the failed shards updateIndexSettings(Settings.builder().putNull("index.routing.allocation.include._name"), indexName); - assertAcked(clusterAdmin().prepareReroute().setRetryFailed(true)); + ClusterRerouteUtils.rerouteRetryFailed(client()); }; unrestorableUseCase( diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestBuilder.java index 2204fd08ae580..4bfa3505667d0 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestBuilder.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestBuilder.java @@ -14,7 +14,10 @@ /** * Builder for a cluster reroute request + * + * @deprecated just build the request directly */ +@Deprecated(forRemoval = true) // temporary compatibility shim public class ClusterRerouteRequestBuilder extends AcknowledgedRequestBuilder< ClusterRerouteRequest, ClusterRerouteResponse, diff --git a/server/src/main/java/org/elasticsearch/client/internal/ClusterAdminClient.java b/server/src/main/java/org/elasticsearch/client/internal/ClusterAdminClient.java index d2ac07cf16479..4f24aa7b93f4a 100644 --- a/server/src/main/java/org/elasticsearch/client/internal/ClusterAdminClient.java +++ b/server/src/main/java/org/elasticsearch/client/internal/ClusterAdminClient.java @@ -203,14 +203,26 @@ public ClusterUpdateSettingsRequestBuilder prepareUpdateSettings() { return new ClusterUpdateSettingsRequestBuilder(this); } + /** + * @deprecated use {@code ClusterRerouteUtils} in tests, or just run the action directly + */ + @Deprecated(forRemoval = true) // temporary compatibility shim public ActionFuture reroute(final ClusterRerouteRequest request) { return execute(TransportClusterRerouteAction.TYPE, request); } + /** + * @deprecated use {@code ClusterRerouteUtils} in tests, or just run the action directly + */ + @Deprecated(forRemoval = true) // temporary compatibility shim public void reroute(final ClusterRerouteRequest request, final ActionListener listener) { execute(TransportClusterRerouteAction.TYPE, request, listener); } + /** + * @deprecated use {@code ClusterRerouteUtils} in tests, or just run the action directly + */ + @Deprecated(forRemoval = true) // temporary compatibility shim public ClusterRerouteRequestBuilder prepareReroute() { return new ClusterRerouteRequestBuilder(this); } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java index 769877ac943e4..47d6198114fc2 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java @@ -9,6 +9,7 @@ package org.elasticsearch.rest.action.admin.cluster; import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; +import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.client.internal.node.NodeClient; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands; @@ -86,7 +87,11 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC if (metric == null) { request.params().put("metric", DEFAULT_METRICS); } - return channel -> client.admin().cluster().reroute(clusterRerouteRequest, new RestRefCountedChunkedToXContentListener<>(channel)); + return channel -> client.execute( + TransportClusterRerouteAction.TYPE, + clusterRerouteRequest, + new RestRefCountedChunkedToXContentListener<>(channel) + ); } @Override diff --git a/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java b/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java index dc0bd57731d98..2ed69810c8905 100644 --- a/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java +++ b/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java @@ -11,6 +11,7 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionType; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; import org.elasticsearch.action.admin.cluster.snapshots.create.TransportCreateSnapshotAction; import org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction; @@ -118,10 +119,11 @@ public void testActions() { .cluster() .prepareCreateSnapshot("repo", "bck") .execute(new AssertingActionListener<>(TransportCreateSnapshotAction.TYPE.name(), client.threadPool())); - client.admin() - .cluster() - .prepareReroute() - .execute(new AssertingActionListener<>(TransportClusterRerouteAction.TYPE.name(), client.threadPool())); + client.execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest(), + new AssertingActionListener<>(TransportClusterRerouteAction.TYPE.name(), client.threadPool()) + ); // choosing arbitrary indices admin actions to test client.admin() diff --git a/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java b/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java index 40064e2b68ed1..8a5d282fe0141 100644 --- a/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java +++ b/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java @@ -1050,19 +1050,18 @@ public void run() { .deleteSnapshot(new DeleteSnapshotRequest(repoName, snapshotName), ActionListener.noop()); })); scheduleNow( - () -> testClusterNodes.randomMasterNodeSafe().client.admin() - .cluster() - .reroute( - new ClusterRerouteRequest().add( - new AllocateEmptyPrimaryAllocationCommand( - index, - shardRouting.shardId().id(), - otherNode.node.getName(), - true - ) - ), - ActionListener.noop() - ) + () -> testClusterNodes.randomMasterNodeSafe().client.execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().add( + new AllocateEmptyPrimaryAllocationCommand( + index, + shardRouting.shardId().id(), + otherNode.node.getName(), + true + ) + ), + ActionListener.noop() + ) ); } else { scheduleSoon(this); diff --git a/test/framework/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteUtils.java b/test/framework/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteUtils.java new file mode 100644 index 0000000000000..3da245ec430af --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.action.admin.cluster.reroute; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.support.ActionTestUtils; +import org.elasticsearch.action.support.SubscribableListener; +import org.elasticsearch.client.internal.ElasticsearchClient; +import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand; + +import static org.elasticsearch.test.ESTestCase.asInstanceOf; +import static org.elasticsearch.test.ESTestCase.safeAwait; +import static org.elasticsearch.test.ESTestCase.safeGet; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; + +/** + * Utilities for invoking {@link TransportClusterRerouteAction} in tests. + */ +public class ClusterRerouteUtils { + private ClusterRerouteUtils() {/* no instances */} + + /** + * Execute {@link TransportClusterRerouteAction} with the given (optional) sequence of {@link AllocationCommand} instances. Asserts that + * this succeeds. + */ + public static void reroute(ElasticsearchClient client, AllocationCommand... allocationCommands) { + doReroute(client, false, allocationCommands); + } + + /** + * Execute {@link TransportClusterRerouteAction} to reset the allocation failure counter. Asserts that this succeeds. + */ + public static void rerouteRetryFailed(ElasticsearchClient client) { + doReroute(client, true); + } + + private static void doReroute(ElasticsearchClient client, boolean retryFailed, AllocationCommand... allocationCommands) { + assertAcked( + safeGet( + client.execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().setRetryFailed(retryFailed).add(allocationCommands) + ) + ) + ); + } + + /** + * Execute {@link TransportClusterRerouteAction} with the given (optional) sequence of {@link AllocationCommand} instances, asserts that + * it fails, and returns the resulting (unwrapped) exception. + */ + public static Exception expectRerouteFailure(ElasticsearchClient client, AllocationCommand... allocationCommands) { + final Exception wrappedException = safeAwait( + SubscribableListener.newForked( + l -> client.execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest().add(allocationCommands), + ActionTestUtils.assertNoSuccessListener(l::onResponse) + ) + ) + ); + return asInstanceOf(Exception.class, wrappedException instanceof ElasticsearchException esx ? esx.unwrapCause() : wrappedException); + } +} diff --git a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java index bf9eba87ee809..49c244167fe19 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java +++ b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java @@ -71,7 +71,6 @@ import static org.apache.lucene.tests.util.LuceneTestCase.expectThrows; import static org.apache.lucene.tests.util.LuceneTestCase.expectThrowsAnyOf; -import static org.elasticsearch.test.ESIntegTestCase.client; import static org.elasticsearch.test.LambdaMatchers.transformedArrayItemsMatch; import static org.elasticsearch.test.LambdaMatchers.transformedItemsMatch; import static org.elasticsearch.test.LambdaMatchers.transformedMatch; @@ -181,10 +180,17 @@ public static void assertBlocked(BaseBroadcastResponse replicatedBroadcastRespon * @param expectedBlockId the expected block id */ public static void assertBlocked(final RequestBuilder builder, @Nullable final Integer expectedBlockId) { - var e = ESTestCase.expectThrows(ClusterBlockException.class, builder); + assertBlocked(expectedBlockId, ESTestCase.expectThrows(ClusterBlockException.class, builder)); + } + + /** + * Checks that the given exception is a {@link ClusterBlockException}; if the given block ID is not {@code null} then the given + * exception must match that ID. + */ + public static void assertBlocked(@Nullable final Integer expectedBlockId, Exception exception) { + final var e = ESTestCase.asInstanceOf(ClusterBlockException.class, exception); assertThat(e.blocks(), not(empty())); - RestStatus status = checkRetryableBlock(e.blocks()) ? RestStatus.TOO_MANY_REQUESTS : RestStatus.FORBIDDEN; - assertThat(e.status(), equalTo(status)); + assertThat(e.status(), equalTo(checkRetryableBlock(e.blocks()) ? RestStatus.TOO_MANY_REQUESTS : RestStatus.FORBIDDEN)); if (expectedBlockId != null) { assertThat( diff --git a/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/existence/FrozenExistenceDeciderIT.java b/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/existence/FrozenExistenceDeciderIT.java index 3e729e9139c2b..154b5cb7f7999 100644 --- a/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/existence/FrozenExistenceDeciderIT.java +++ b/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/existence/FrozenExistenceDeciderIT.java @@ -7,7 +7,7 @@ package org.elasticsearch.xpack.autoscaling.existence; -import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequest; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.blobcache.BlobCachePlugin; import org.elasticsearch.cluster.health.ClusterHealthStatus; @@ -141,7 +141,7 @@ public void testZeroToOne() throws Exception { assertBusy(() -> { // cause a bit of cluster activity using an empty reroute call in case the `wait-for-index-colour` ILM step missed the // notification that partial-index is now GREEN. - client().admin().cluster().reroute(new ClusterRerouteRequest()).actionGet(); + ClusterRerouteUtils.reroute(client()); String[] indices = indices(); assertThat(indices, arrayContaining(PARTIAL_INDEX_NAME)); assertThat(indices, not(arrayContaining(INDEX_NAME))); diff --git a/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/storage/ReactiveStorageIT.java b/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/storage/ReactiveStorageIT.java index 9a171663e9dfc..25bd08afcad72 100644 --- a/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/storage/ReactiveStorageIT.java +++ b/x-pack/plugin/autoscaling/src/internalClusterTest/java/org/elasticsearch/xpack/autoscaling/storage/ReactiveStorageIT.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.autoscaling.storage; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.indices.shrink.ResizeType; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.index.IndexRequestBuilder; @@ -331,7 +332,7 @@ public void testScaleWhileShrinking() throws Exception { long enoughSpaceForColocation = used + LOW_WATERMARK_BYTES; setTotalSpace(dataNode1Name, enoughSpaceForColocation); setTotalSpace(dataNode2Name, enoughSpaceForColocation); - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); waitForRelocation(); // Ensure that the relocated shard index files are removed from the data 2 node, @@ -385,10 +386,10 @@ public void testScaleWhileShrinking() throws Exception { long tooLittleSpaceForShrink = requiredSpaceForShrink - Math.min(LOW_WATERMARK_BYTES - HIGH_WATERMARK_BYTES, used) - 1; assert tooLittleSpaceForShrink <= requiredSpaceForShrink; setTotalSpace(dataNode1Name, tooLittleSpaceForShrink); - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); assertThat(clusterAdmin().prepareHealth(shrinkName).get().getUnassignedShards(), equalTo(1)); setTotalSpace(dataNode1Name, tooLittleSpaceForShrink + 1); - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); ensureGreen(); indicesAdmin().prepareDelete(indexName).get(); @@ -495,10 +496,10 @@ public void testScaleDuringSplitOrClone() throws Exception { long tooLittleSpaceForClone = requiredSpaceForClone - Math.min(LOW_WATERMARK_BYTES - HIGH_WATERMARK_BYTES, used) - 1; assert tooLittleSpaceForClone <= requiredSpaceForClone; setTotalSpace(dataNode1Name, tooLittleSpaceForClone); - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); assertThat(clusterAdmin().prepareHealth(cloneName).get().getUnassignedShards(), equalTo(resizedShardCount)); setTotalSpace(dataNode1Name, requiredSpaceForClone); - assertAcked(clusterAdmin().prepareReroute()); + ClusterRerouteUtils.reroute(client()); ensureGreen(); indicesAdmin().prepareDelete(indexName).get(); diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlDisruptionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlDisruptionIT.java index e005e2143522b..df1b2c9f00f49 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlDisruptionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlDisruptionIT.java @@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.admin.cluster.node.tasks.list.TransportListTasksAction; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.cluster.coordination.Coordinator; import org.elasticsearch.cluster.coordination.FollowersChecker; import org.elasticsearch.cluster.coordination.LeaderChecker; @@ -29,7 +30,6 @@ import java.util.concurrent.TimeUnit; import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; @ESIntegTestCase.ClusterScope(scope = TEST, minNumDataNodes = 2, maxNumDataNodes = 4) public class EsqlDisruptionIT extends EsqlActionIT { @@ -140,7 +140,7 @@ private void clearDisruption() { try { internalCluster().clearDisruptionScheme(false); ensureFullyConnectedCluster(); - assertBusy(() -> assertAcked(clusterAdmin().prepareReroute().setRetryFailed(true)), 1, TimeUnit.MINUTES); + assertBusy(() -> ClusterRerouteUtils.rerouteRetryFailed(client()), 1, TimeUnit.MINUTES); ensureYellow(); } catch (Exception e) { throw new AssertionError(e); diff --git a/x-pack/plugin/frozen-indices/src/internalClusterTest/java/org/elasticsearch/index/engine/frozen/FrozenIndexIT.java b/x-pack/plugin/frozen-indices/src/internalClusterTest/java/org/elasticsearch/index/engine/frozen/FrozenIndexIT.java index 7b33fe670efd7..e378ce06611c6 100644 --- a/x-pack/plugin/frozen-indices/src/internalClusterTest/java/org/elasticsearch/index/engine/frozen/FrozenIndexIT.java +++ b/x-pack/plugin/frozen-indices/src/internalClusterTest/java/org/elasticsearch/index/engine/frozen/FrozenIndexIT.java @@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.DocWriteResponse; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.search.ClosePointInTimeRequest; import org.elasticsearch.action.search.OpenPointInTimeRequest; import org.elasticsearch.action.search.SearchType; @@ -85,7 +86,7 @@ public void testTimestampRangeRecalculatedOnStalePrimaryAllocation() throws IOEx final String excludeSetting = INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getConcreteSettingForNamespace("_name").getKey(); updateIndexSettings(Settings.builder().put(excludeSetting, nodeNames.get(0)), "index"); - assertAcked(clusterAdmin().prepareReroute().add(new CancelAllocationCommand("index", 0, nodeNames.get(0), true))); + ClusterRerouteUtils.reroute(client(), new CancelAllocationCommand("index", 0, nodeNames.get(0), true)); assertThat(clusterAdmin().prepareHealth("index").get().getUnassignedShards(), equalTo(1)); assertThat(client().prepareDelete("index", indexResponse.getId()).get().status(), equalTo(RestStatus.OK)); @@ -107,7 +108,7 @@ public void testTimestampRangeRecalculatedOnStalePrimaryAllocation() throws IOEx updateIndexSettings(Settings.builder().putNull(excludeSetting), "index"); assertThat(clusterAdmin().prepareHealth("index").get().getUnassignedShards(), equalTo(2)); - assertAcked(clusterAdmin().prepareReroute().add(new AllocateStalePrimaryAllocationCommand("index", 0, nodeNames.get(0), true))); + ClusterRerouteUtils.reroute(client(), new AllocateStalePrimaryAllocationCommand("index", 0, nodeNames.get(0), true)); ensureYellowAndNoInitializingShards("index"); diff --git a/x-pack/plugin/shutdown/src/internalClusterTest/java/org/elasticsearch/xpack/shutdown/NodeShutdownTasksIT.java b/x-pack/plugin/shutdown/src/internalClusterTest/java/org/elasticsearch/xpack/shutdown/NodeShutdownTasksIT.java index cac1bdd096be9..46f568d286f9e 100644 --- a/x-pack/plugin/shutdown/src/internalClusterTest/java/org/elasticsearch/xpack/shutdown/NodeShutdownTasksIT.java +++ b/x-pack/plugin/shutdown/src/internalClusterTest/java/org/elasticsearch/xpack/shutdown/NodeShutdownTasksIT.java @@ -12,6 +12,7 @@ import org.elasticsearch.ResourceAlreadyExistsException; import org.elasticsearch.TransportVersion; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.client.internal.Client; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterState; @@ -106,7 +107,7 @@ public void testTasksAreNotAssignedToShuttingDownNode() throws Exception { // Tell the persistent task executor it can start allocating the task startTask.set(true); // Issue a new cluster state update to force task assignment - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); // Wait until the task has been assigned to a node assertBusy(() -> assertNotNull("expected to have candidate nodes chosen for task", candidates.get())); // Check that the node that is not shut down is the only candidate diff --git a/x-pack/plugin/slm/src/internalClusterTest/java/org/elasticsearch/xpack/slm/SLMSnapshotBlockingIntegTests.java b/x-pack/plugin/slm/src/internalClusterTest/java/org/elasticsearch/xpack/slm/SLMSnapshotBlockingIntegTests.java index 3787761a2b287..a64df7f871d97 100644 --- a/x-pack/plugin/slm/src/internalClusterTest/java/org/elasticsearch/xpack/slm/SLMSnapshotBlockingIntegTests.java +++ b/x-pack/plugin/slm/src/internalClusterTest/java/org/elasticsearch/xpack/slm/SLMSnapshotBlockingIntegTests.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.slm; import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteUtils; import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest; import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse; @@ -248,7 +249,7 @@ public void testRetentionWhileSnapshotInProgress() throws Exception { // Check that the snapshot created by the policy has been removed by retention assertBusy(() -> { // Trigger a cluster state update so that it re-checks for a snapshot in progress - clusterAdmin().prepareReroute().get(); + ClusterRerouteUtils.reroute(client()); logger.info("--> waiting for snapshot to be deleted"); try { SnapshotsStatusResponse s = getSnapshotStatus(completedSnapshotName); From 5dca7a804f69bf4002b8d6e8fc41cecb70e087a6 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Tue, 11 Jun 2024 16:45:17 +0200 Subject: [PATCH 14/18] Fix small bug in TimeSeriesSortedSourceOperatorFactory (#109580) Only initialize `currentTsid` variable is queue isn't empty Closes #109578 --- muted-tests.yml | 3 --- .../compute/lucene/TimeSeriesSortedSourceOperatorFactory.java | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index 4f4d6da837a82..03a0df5cc3955 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -61,9 +61,6 @@ tests: issue: https://github.com/elastic/elasticsearch/issues/109409 - class: DenseVectorMappingUpdateIT issue: "https://github.com/elastic/elasticsearch/issues/109571" -- class: "org.elasticsearch.compute.lucene.TimeSeriesSortedSourceOperatorTests" - issue: "https://github.com/elastic/elasticsearch/issues/109578" - method: "testMatchNone" # Examples: # diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/TimeSeriesSortedSourceOperatorFactory.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/TimeSeriesSortedSourceOperatorFactory.java index 8b52aa84aef21..3dde3ba75be78 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/TimeSeriesSortedSourceOperatorFactory.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/TimeSeriesSortedSourceOperatorFactory.java @@ -275,8 +275,8 @@ protected boolean lessThan(Leaf a, Leaf b) { void consume() throws IOException { if (queue != null) { - currentTsid = BytesRef.deepCopyOf(queue.top().timeSeriesHash); if (queue.size() > 0) { + currentTsid = BytesRef.deepCopyOf(queue.top().timeSeriesHash); queue.top().reinitializeIfNeeded(Thread.currentThread()); } while (queue.size() > 0) { From ccef9e7369553dbad6e6b1a2281936fd1a4398e0 Mon Sep 17 00:00:00 2001 From: Fang Xing <155562079+fang-xing-esql@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:47:18 -0400 Subject: [PATCH 15/18] [ES|QL] Support Named and Positional Parameters in EsqlQueryRequest (#108421) * support named and positional parameters in EsqlQueryRequest --- docs/changelog/108421.yaml | 6 + .../xpack/esql/core/util/StringUtils.java | 22 + .../xpack/esql/qa/rest/RestEsqlTestCase.java | 56 +- .../esql/src/main/antlr/EsqlBaseLexer.g4 | 5 + .../esql/src/main/antlr/EsqlBaseLexer.tokens | 129 +- .../esql/src/main/antlr/EsqlBaseParser.g4 | 7 +- .../esql/src/main/antlr/EsqlBaseParser.tokens | 129 +- .../xpack/esql/action/EsqlCapabilities.java | 10 +- .../xpack/esql/action/EsqlQueryRequest.java | 9 +- .../xpack/esql/action/RequestXContent.java | 153 +- .../xpack/esql/parser/AstBuilder.java | 6 +- .../xpack/esql/parser/ContentLocation.java | 30 - .../xpack/esql/parser/EsqlBaseLexer.interp | 5 +- .../xpack/esql/parser/EsqlBaseLexer.java | 1774 +++++++++-------- .../xpack/esql/parser/EsqlBaseParser.interp | 5 +- .../xpack/esql/parser/EsqlBaseParser.java | 1560 ++++++++------- .../parser/EsqlBaseParserBaseListener.java | 28 +- .../parser/EsqlBaseParserBaseVisitor.java | 16 +- .../esql/parser/EsqlBaseParserListener.java | 32 +- .../esql/parser/EsqlBaseParserVisitor.java | 18 +- .../xpack/esql/parser/EsqlParser.java | 61 +- .../xpack/esql/parser/ExpressionBuilder.java | 99 +- .../xpack/esql/parser/LogicalPlanBuilder.java | 17 +- .../xpack/esql/parser/QueryParam.java | 24 + .../xpack/esql/parser/QueryParams.java | 83 + .../xpack/esql/parser/TypedParamValue.java | 70 - .../xpack/esql/session/EsqlSession.java | 4 +- .../esql/action/EsqlQueryRequestTests.java | 163 +- .../xpack/esql/analysis/VerifierTests.java | 15 +- .../esql/parser/StatementParserTests.java | 382 +++- .../rest-api-spec/test/esql/10_basic.yml | 45 +- 31 files changed, 2846 insertions(+), 2117 deletions(-) create mode 100644 docs/changelog/108421.yaml delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ContentLocation.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParam.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParams.java delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/TypedParamValue.java diff --git a/docs/changelog/108421.yaml b/docs/changelog/108421.yaml new file mode 100644 index 0000000000000..1f077a4a2cb7c --- /dev/null +++ b/docs/changelog/108421.yaml @@ -0,0 +1,6 @@ +pr: 108421 +summary: "[ES|QL] Support Named and Positional Parameters in `EsqlQueryRequest`" +area: ES|QL +type: enhancement +issues: + - 107029 diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/util/StringUtils.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/util/StringUtils.java index 1eb7e1cce5cbb..47246a4e190dd 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/util/StringUtils.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/util/StringUtils.java @@ -392,4 +392,26 @@ public static String qualifyAndJoinIndices(String cluster, String[] indices) { public static boolean isQualified(String indexWildcard) { return indexWildcard.indexOf(REMOTE_CLUSTER_INDEX_SEPARATOR) > 0; } + + public static boolean isInteger(String value) { + for (char c : value.trim().toCharArray()) { + if (Character.isDigit(c) == false) { + return false; + } + } + return true; + } + + public static boolean isValidParamName(String value) { + // A valid name starts with a letter and contain only letter, digit or _ + if (Character.isLetter(value.charAt(0)) == false) { + return false; + } + for (char c : value.trim().toCharArray()) { + if (Character.isLetterOrDigit(c) == false && c != '_') { + return false; + } + } + return true; + } } diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java index 0c5ec5eac716e..a672e4a50612c 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java @@ -485,36 +485,39 @@ public void testErrorMessageForEmptyParams() throws IOException { public void testErrorMessageForInvalidParams() throws IOException { ResponseException re = expectThrows( ResponseException.class, - () -> runEsql(requestObjectBuilder().query("row a = 1").params("[{\"x\":\"y\"}]")) + () -> runEsqlSync( + requestObjectBuilder().query("row a = 1 | eval x = ?, y = ?") + .params( + "[{\"1\": \"v1\"}, {\"1-\": \"v1\"}, {\"_a\": \"v1\"}, {\"@-#\": \"v1\"}, true, 123, " + + "{\"type\": \"byte\", \"value\": 5}]" + ) + ) ); - assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("Required [value, type]")); - } - - public void testErrorMessageForMissingTypeInParams() throws IOException { - ResponseException re = expectThrows( - ResponseException.class, - () -> runEsql(requestObjectBuilder().query("row a = 1").params("[\"x\", 123, true, {\"value\": \"y\"}]")) - ); - assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("Required [type]")); - } - - public void testErrorMessageForMissingValueInParams() throws IOException { - ResponseException re = expectThrows( + String error = EntityUtils.toString(re.getResponse().getEntity()).replaceAll("\\\\\n\s+\\\\", ""); + assertThat(error, containsString("[1] is not a valid parameter name")); + assertThat(error, containsString("[1-] is not a valid parameter name")); + assertThat(error, containsString("[_a] is not a valid parameter name")); + assertThat(error, containsString("[@-#] is not a valid parameter name")); + assertThat(error, containsString("Params cannot contain both named and unnamed parameters")); + assertThat(error, containsString("Cannot parse more than one key:value pair as parameter")); + re = expectThrows( ResponseException.class, - () -> runEsql(requestObjectBuilder().query("row a = 1").params("[\"x\", 123, true, {\"type\": \"y\"}]")) + () -> runEsqlSync(requestObjectBuilder().query("row a = ?0, b= ?2").params("[{\"n1\": \"v1\"}]")) ); - assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("Required [value]")); - } - - public void testErrorMessageForInvalidTypeInParams() throws IOException { - ResponseException re = expectThrows( - ResponseException.class, - () -> runEsqlSync(requestObjectBuilder().query("row a = 1 | eval x = ?").params("[{\"type\": \"byte\", \"value\": 5}]")) + assertThat( + EntityUtils.toString(re.getResponse().getEntity()), + containsString("No parameter is defined for position 0, did you mean position 1") ); assertThat( EntityUtils.toString(re.getResponse().getEntity()), - containsString("EVAL does not support type [byte] in expression [?]") + containsString("No parameter is defined for position 2, did you mean position 1") + ); + + re = expectThrows( + ResponseException.class, + () -> runEsqlSync(requestObjectBuilder().query("row a = ?n0").params("[{\"n1\": \"v1\"}]")) ); + assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("Unknown query parameter [n0], did you mean [n1]")); } public void testErrorMessageForLiteralDateMathOverflow() throws IOException { @@ -559,12 +562,9 @@ private void assertExceptionForDateMath(String dateMathString, String errorSubst public void testErrorMessageForArrayValuesInParams() throws IOException { ResponseException re = expectThrows( ResponseException.class, - () -> runEsql(requestObjectBuilder().query("row a = 1 | eval x = ?").params("[{\"type\": \"integer\", \"value\": [5, 6, 7]}]")) - ); - assertThat( - EntityUtils.toString(re.getResponse().getEntity()), - containsString("[params] value doesn't support values of type: START_ARRAY") + () -> runEsql(requestObjectBuilder().query("row a = 1 | eval x = ?").params("[{\"n1\": [5, 6, 7]}]")) ); + assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("n1=[5, 6, 7] is not supported as a parameter")); } private static String expectedTextBody(String format, int count, @Nullable Character csvDelimiter) { diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 index fb424b16ac403..61ce9bd9152e8 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.g4 @@ -156,6 +156,11 @@ ASTERISK : '*'; SLASH : '/'; PERCENT : '%'; +NAMED_OR_POSITIONAL_PARAM + : PARAM LETTER UNQUOTED_ID_BODY* + | PARAM DIGIT+ + ; + // Brackets are funny. We can happen upon a CLOSING_BRACKET in two ways - one // way is to start in an explain command which then shifts us to expression // mode. Thus, the two popModes on CLOSING_BRACKET. The other way could as diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens index 30ce0d5eea55b..04798fc3dca8a 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens @@ -65,62 +65,63 @@ MINUS=64 ASTERISK=65 SLASH=66 PERCENT=67 -OPENING_BRACKET=68 -CLOSING_BRACKET=69 -UNQUOTED_IDENTIFIER=70 -QUOTED_IDENTIFIER=71 -EXPR_LINE_COMMENT=72 -EXPR_MULTILINE_COMMENT=73 -EXPR_WS=74 -METADATA=75 -FROM_LINE_COMMENT=76 -FROM_MULTILINE_COMMENT=77 -FROM_WS=78 -ID_PATTERN=79 -PROJECT_LINE_COMMENT=80 -PROJECT_MULTILINE_COMMENT=81 -PROJECT_WS=82 -AS=83 -RENAME_LINE_COMMENT=84 -RENAME_MULTILINE_COMMENT=85 -RENAME_WS=86 -ON=87 -WITH=88 -ENRICH_POLICY_NAME=89 -ENRICH_LINE_COMMENT=90 -ENRICH_MULTILINE_COMMENT=91 -ENRICH_WS=92 -ENRICH_FIELD_LINE_COMMENT=93 -ENRICH_FIELD_MULTILINE_COMMENT=94 -ENRICH_FIELD_WS=95 -LOOKUP_LINE_COMMENT=96 -LOOKUP_MULTILINE_COMMENT=97 -LOOKUP_WS=98 -LOOKUP_FIELD_LINE_COMMENT=99 -LOOKUP_FIELD_MULTILINE_COMMENT=100 -LOOKUP_FIELD_WS=101 -MVEXPAND_LINE_COMMENT=102 -MVEXPAND_MULTILINE_COMMENT=103 -MVEXPAND_WS=104 -INFO=105 -SHOW_LINE_COMMENT=106 -SHOW_MULTILINE_COMMENT=107 -SHOW_WS=108 -FUNCTIONS=109 -META_LINE_COMMENT=110 -META_MULTILINE_COMMENT=111 -META_WS=112 -COLON=113 -SETTING=114 -SETTING_LINE_COMMENT=115 -SETTTING_MULTILINE_COMMENT=116 -SETTING_WS=117 -METRICS_LINE_COMMENT=118 -METRICS_MULTILINE_COMMENT=119 -METRICS_WS=120 -CLOSING_METRICS_LINE_COMMENT=121 -CLOSING_METRICS_MULTILINE_COMMENT=122 -CLOSING_METRICS_WS=123 +NAMED_OR_POSITIONAL_PARAM=68 +OPENING_BRACKET=69 +CLOSING_BRACKET=70 +UNQUOTED_IDENTIFIER=71 +QUOTED_IDENTIFIER=72 +EXPR_LINE_COMMENT=73 +EXPR_MULTILINE_COMMENT=74 +EXPR_WS=75 +METADATA=76 +FROM_LINE_COMMENT=77 +FROM_MULTILINE_COMMENT=78 +FROM_WS=79 +ID_PATTERN=80 +PROJECT_LINE_COMMENT=81 +PROJECT_MULTILINE_COMMENT=82 +PROJECT_WS=83 +AS=84 +RENAME_LINE_COMMENT=85 +RENAME_MULTILINE_COMMENT=86 +RENAME_WS=87 +ON=88 +WITH=89 +ENRICH_POLICY_NAME=90 +ENRICH_LINE_COMMENT=91 +ENRICH_MULTILINE_COMMENT=92 +ENRICH_WS=93 +ENRICH_FIELD_LINE_COMMENT=94 +ENRICH_FIELD_MULTILINE_COMMENT=95 +ENRICH_FIELD_WS=96 +LOOKUP_LINE_COMMENT=97 +LOOKUP_MULTILINE_COMMENT=98 +LOOKUP_WS=99 +LOOKUP_FIELD_LINE_COMMENT=100 +LOOKUP_FIELD_MULTILINE_COMMENT=101 +LOOKUP_FIELD_WS=102 +MVEXPAND_LINE_COMMENT=103 +MVEXPAND_MULTILINE_COMMENT=104 +MVEXPAND_WS=105 +INFO=106 +SHOW_LINE_COMMENT=107 +SHOW_MULTILINE_COMMENT=108 +SHOW_WS=109 +FUNCTIONS=110 +META_LINE_COMMENT=111 +META_MULTILINE_COMMENT=112 +META_WS=113 +COLON=114 +SETTING=115 +SETTING_LINE_COMMENT=116 +SETTTING_MULTILINE_COMMENT=117 +SETTING_WS=118 +METRICS_LINE_COMMENT=119 +METRICS_MULTILINE_COMMENT=120 +METRICS_WS=121 +CLOSING_METRICS_LINE_COMMENT=122 +CLOSING_METRICS_MULTILINE_COMMENT=123 +CLOSING_METRICS_WS=124 'dissect'=1 'drop'=2 'enrich'=3 @@ -177,11 +178,11 @@ CLOSING_METRICS_WS=123 '*'=65 '/'=66 '%'=67 -']'=69 -'metadata'=75 -'as'=83 -'on'=87 -'with'=88 -'info'=105 -'functions'=109 -':'=113 +']'=70 +'metadata'=76 +'as'=84 +'on'=88 +'with'=89 +'info'=106 +'functions'=110 +':'=114 diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 index 29892d464c0e5..69d65ea9a214b 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 @@ -170,13 +170,18 @@ constant | decimalValue #decimalLiteral | integerValue #integerLiteral | booleanValue #booleanLiteral - | PARAM #inputParam + | params #inputParams | string #stringLiteral | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET #numericArrayLiteral | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET #booleanArrayLiteral | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET #stringArrayLiteral ; +params + : PARAM #inputParam + | NAMED_OR_POSITIONAL_PARAM #inputNamedOrPositionalParam + ; + limitCommand : LIMIT INTEGER_LITERAL ; diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens index 30ce0d5eea55b..04798fc3dca8a 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens @@ -65,62 +65,63 @@ MINUS=64 ASTERISK=65 SLASH=66 PERCENT=67 -OPENING_BRACKET=68 -CLOSING_BRACKET=69 -UNQUOTED_IDENTIFIER=70 -QUOTED_IDENTIFIER=71 -EXPR_LINE_COMMENT=72 -EXPR_MULTILINE_COMMENT=73 -EXPR_WS=74 -METADATA=75 -FROM_LINE_COMMENT=76 -FROM_MULTILINE_COMMENT=77 -FROM_WS=78 -ID_PATTERN=79 -PROJECT_LINE_COMMENT=80 -PROJECT_MULTILINE_COMMENT=81 -PROJECT_WS=82 -AS=83 -RENAME_LINE_COMMENT=84 -RENAME_MULTILINE_COMMENT=85 -RENAME_WS=86 -ON=87 -WITH=88 -ENRICH_POLICY_NAME=89 -ENRICH_LINE_COMMENT=90 -ENRICH_MULTILINE_COMMENT=91 -ENRICH_WS=92 -ENRICH_FIELD_LINE_COMMENT=93 -ENRICH_FIELD_MULTILINE_COMMENT=94 -ENRICH_FIELD_WS=95 -LOOKUP_LINE_COMMENT=96 -LOOKUP_MULTILINE_COMMENT=97 -LOOKUP_WS=98 -LOOKUP_FIELD_LINE_COMMENT=99 -LOOKUP_FIELD_MULTILINE_COMMENT=100 -LOOKUP_FIELD_WS=101 -MVEXPAND_LINE_COMMENT=102 -MVEXPAND_MULTILINE_COMMENT=103 -MVEXPAND_WS=104 -INFO=105 -SHOW_LINE_COMMENT=106 -SHOW_MULTILINE_COMMENT=107 -SHOW_WS=108 -FUNCTIONS=109 -META_LINE_COMMENT=110 -META_MULTILINE_COMMENT=111 -META_WS=112 -COLON=113 -SETTING=114 -SETTING_LINE_COMMENT=115 -SETTTING_MULTILINE_COMMENT=116 -SETTING_WS=117 -METRICS_LINE_COMMENT=118 -METRICS_MULTILINE_COMMENT=119 -METRICS_WS=120 -CLOSING_METRICS_LINE_COMMENT=121 -CLOSING_METRICS_MULTILINE_COMMENT=122 -CLOSING_METRICS_WS=123 +NAMED_OR_POSITIONAL_PARAM=68 +OPENING_BRACKET=69 +CLOSING_BRACKET=70 +UNQUOTED_IDENTIFIER=71 +QUOTED_IDENTIFIER=72 +EXPR_LINE_COMMENT=73 +EXPR_MULTILINE_COMMENT=74 +EXPR_WS=75 +METADATA=76 +FROM_LINE_COMMENT=77 +FROM_MULTILINE_COMMENT=78 +FROM_WS=79 +ID_PATTERN=80 +PROJECT_LINE_COMMENT=81 +PROJECT_MULTILINE_COMMENT=82 +PROJECT_WS=83 +AS=84 +RENAME_LINE_COMMENT=85 +RENAME_MULTILINE_COMMENT=86 +RENAME_WS=87 +ON=88 +WITH=89 +ENRICH_POLICY_NAME=90 +ENRICH_LINE_COMMENT=91 +ENRICH_MULTILINE_COMMENT=92 +ENRICH_WS=93 +ENRICH_FIELD_LINE_COMMENT=94 +ENRICH_FIELD_MULTILINE_COMMENT=95 +ENRICH_FIELD_WS=96 +LOOKUP_LINE_COMMENT=97 +LOOKUP_MULTILINE_COMMENT=98 +LOOKUP_WS=99 +LOOKUP_FIELD_LINE_COMMENT=100 +LOOKUP_FIELD_MULTILINE_COMMENT=101 +LOOKUP_FIELD_WS=102 +MVEXPAND_LINE_COMMENT=103 +MVEXPAND_MULTILINE_COMMENT=104 +MVEXPAND_WS=105 +INFO=106 +SHOW_LINE_COMMENT=107 +SHOW_MULTILINE_COMMENT=108 +SHOW_WS=109 +FUNCTIONS=110 +META_LINE_COMMENT=111 +META_MULTILINE_COMMENT=112 +META_WS=113 +COLON=114 +SETTING=115 +SETTING_LINE_COMMENT=116 +SETTTING_MULTILINE_COMMENT=117 +SETTING_WS=118 +METRICS_LINE_COMMENT=119 +METRICS_MULTILINE_COMMENT=120 +METRICS_WS=121 +CLOSING_METRICS_LINE_COMMENT=122 +CLOSING_METRICS_MULTILINE_COMMENT=123 +CLOSING_METRICS_WS=124 'dissect'=1 'drop'=2 'enrich'=3 @@ -177,11 +178,11 @@ CLOSING_METRICS_WS=123 '*'=65 '/'=66 '%'=67 -']'=69 -'metadata'=75 -'as'=83 -'on'=87 -'with'=88 -'info'=105 -'functions'=109 -':'=113 +']'=70 +'metadata'=76 +'as'=84 +'on'=88 +'with'=89 +'info'=106 +'functions'=110 +':'=114 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 9e8553911268f..3eef9f7356b39 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -67,13 +67,18 @@ public class EsqlCapabilities { */ private static final String REPEAT = "repeat"; - public static final Set CAPABILITIES = capabilities(); - /** * Cast string literals to datetime in addition and subtraction when the other side is a date or time interval. */ public static final String STRING_LITERAL_AUTO_CASTING_TO_DATETIME_ADD_SUB = "string_literal_auto_casting_to_datetime_add_sub"; + /** + * Support for named or positional parameters in EsqlQueryRequest. + */ + private static final String NAMED_POSITIONAL_PARAMETER = "named_positional_parameter"; + + public static final Set CAPABILITIES = capabilities(); + private static Set capabilities() { List caps = new ArrayList<>(); caps.add(FN_CBRT); @@ -83,6 +88,7 @@ private static Set capabilities() { caps.add(METADATA_IGNORED_FIELD); caps.add(FN_MV_APPEND); caps.add(REPEAT); + caps.add(NAMED_POSITIONAL_PARAMETER); if (Build.current().isSnapshot()) { caps.add(LOOKUP_COMMAND); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java index 542b220d398d6..e81c9919fe0a3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java @@ -21,12 +21,11 @@ import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.TaskId; import org.elasticsearch.xpack.esql.Column; -import org.elasticsearch.xpack.esql.parser.TypedParamValue; +import org.elasticsearch.xpack.esql.parser.QueryParams; import org.elasticsearch.xpack.esql.plugin.QueryPragmas; import java.io.IOException; import java.util.Iterator; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TreeMap; @@ -46,7 +45,7 @@ public class EsqlQueryRequest extends org.elasticsearch.xpack.core.esql.action.E private Locale locale; private QueryBuilder filter; private QueryPragmas pragmas = new QueryPragmas(Settings.EMPTY); - private List params = List.of(); + private QueryParams params = QueryParams.EMPTY; private TimeValue waitForCompletionTimeout = DEFAULT_WAIT_FOR_COMPLETION; private TimeValue keepAlive = DEFAULT_KEEP_ALIVE; private boolean keepOnCompletion; @@ -159,11 +158,11 @@ public QueryPragmas pragmas() { return pragmas; } - public List params() { + public QueryParams params() { return params; } - public void params(List params) { + public void params(QueryParams params) { this.params = params; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java index 793f453d5ebf5..2c6b5e7a6b490 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java @@ -10,42 +10,59 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.query.AbstractQueryBuilder; -import org.elasticsearch.xcontent.ConstructingObjectParser; import org.elasticsearch.xcontent.ObjectParser; import org.elasticsearch.xcontent.ParseField; import org.elasticsearch.xcontent.XContentLocation; import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentParser; -import org.elasticsearch.xpack.esql.parser.ContentLocation; -import org.elasticsearch.xpack.esql.parser.TypedParamValue; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.parser.QueryParam; +import org.elasticsearch.xpack.esql.parser.QueryParams; import org.elasticsearch.xpack.esql.plugin.QueryPragmas; +import org.elasticsearch.xpack.esql.type.EsqlDataTypes; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.function.Supplier; -import static org.elasticsearch.common.xcontent.XContentParserUtils.parseFieldsValue; -import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg; -import static org.elasticsearch.xcontent.ObjectParser.ValueType.VALUE_ARRAY; +import static org.elasticsearch.xcontent.ObjectParser.ValueType.VALUE_OBJECT_ARRAY; +import static org.elasticsearch.xpack.esql.core.util.StringUtils.isValidParamName; /** Static methods for parsing xcontent requests to transport requests. */ final class RequestXContent { - private static final ConstructingObjectParser PARAM_PARSER = new ConstructingObjectParser<>( - "params", - true, - objects -> new TypedParamValue((String) objects[1], objects[0]) - ); - private static final ParseField VALUE = new ParseField("value"); - private static final ParseField TYPE = new ParseField("type"); + private static class TempObjects { + Map fields = new HashMap<>(); + + TempObjects() {} - static { - PARAM_PARSER.declareField(constructorArg(), (p, c) -> parseFieldsValue(p), VALUE, ObjectParser.ValueType.VALUE); - PARAM_PARSER.declareString(constructorArg(), TYPE); + void addField(String key, Object value) { + fields.put(key, value); + } + + String fields() { + StringBuffer s = new StringBuffer(); + for (Map.Entry entry : fields.entrySet()) { + if (s.length() > 0) { + s.append(", "); + } + s.append("{").append(entry.getKey()).append(":").append(entry.getValue()).append("}"); + } + return s.toString(); + } } + private static final ObjectParser PARAM_PARSER = new ObjectParser<>( + "params", + TempObjects::addField, + TempObjects::new + ); + static final ParseField QUERY_FIELD = new ParseField("query"); private static final ParseField COLUMNAR_FIELD = new ParseField("columnar"); private static final ParseField FILTER_FIELD = new ParseField("filter"); @@ -81,7 +98,7 @@ private static void objectParserCommon(ObjectParser parser) (p, c) -> new QueryPragmas(Settings.builder().loadFromMap(p.map()).build()), PRAGMA_FIELD ); - parser.declareField(EsqlQueryRequest::params, RequestXContent::parseParams, PARAMS_FIELD, VALUE_ARRAY); + parser.declareField(EsqlQueryRequest::params, RequestXContent::parseParams, PARAMS_FIELD, VALUE_OBJECT_ARRAY); parser.declareString((request, localeTag) -> request.locale(Locale.forLanguageTag(localeTag)), LOCALE_FIELD); parser.declareBoolean(EsqlQueryRequest::profile, PROFILE_FIELD); parser.declareField((p, r, c) -> new ParseTables(r, p).parseTables(), TABLES_FIELD, ObjectParser.ValueType.OBJECT); @@ -112,82 +129,94 @@ private static ObjectParser objectParserAsync(Supplier parseParams(XContentParser p) throws IOException { - List result = new ArrayList<>(); + private static QueryParams parseParams(XContentParser p) throws IOException { + List namedParams = new ArrayList<>(); + List unNamedParams = new ArrayList<>(); + List errors = new ArrayList<>(); XContentParser.Token token = p.currentToken(); if (token == XContentParser.Token.START_ARRAY) { Object value = null; - String type = null; - TypedParamValue previousParam = null; - TypedParamValue currentParam; + DataType type = null; + QueryParam currentParam = null; + TempObjects param; while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) { XContentLocation loc = p.getTokenLocation(); - if (token == XContentParser.Token.START_OBJECT) { - // we are at the start of a value/type pair... hopefully - currentParam = PARAM_PARSER.apply(p, null); - /* - * Always set the xcontentlocation for the first param just in case the first one happens to not meet the parsing rules - * that are checked later in validateParams method. - * Also, set the xcontentlocation of the param that is different from the previous param in list when it comes to - * its type being explicitly set or inferred. - */ - if ((previousParam != null && previousParam.hasExplicitType() == false) || result.isEmpty()) { - currentParam.tokenLocation(toProto(loc)); + param = PARAM_PARSER.apply(p, null); + if (param.fields.size() > 1) { + errors.add( + new XContentParseException( + loc, + "Cannot parse more than one key:value pair as parameter, found [" + param.fields() + "]" + ) + ); + } + for (Map.Entry entry : param.fields.entrySet()) { + if (isValidParamName(entry.getKey()) == false) { + errors.add( + new XContentParseException( + loc, + "[" + + entry.getKey() + + "] is not a valid parameter name, " + + "a valid parameter name starts with a letter and contains letters, digits and underscores only" + ) + ); + } + type = EsqlDataTypes.fromJava(entry.getValue()); + if (type == null) { + errors.add(new XContentParseException(loc, entry + " is not supported as a parameter")); + } + currentParam = new QueryParam(entry.getKey(), entry.getValue(), type); + namedParams.add(currentParam); } } else { if (token == XContentParser.Token.VALUE_STRING) { value = p.text(); - type = "keyword"; + type = DataType.KEYWORD; } else if (token == XContentParser.Token.VALUE_NUMBER) { XContentParser.NumberType numberType = p.numberType(); if (numberType == XContentParser.NumberType.INT) { value = p.intValue(); - type = "integer"; + type = DataType.INTEGER; } else if (numberType == XContentParser.NumberType.LONG) { value = p.longValue(); - type = "long"; + type = DataType.LONG; } else if (numberType == XContentParser.NumberType.DOUBLE) { value = p.doubleValue(); - type = "double"; + type = DataType.DOUBLE; } } else if (token == XContentParser.Token.VALUE_BOOLEAN) { value = p.booleanValue(); - type = "boolean"; + type = DataType.BOOLEAN; } else if (token == XContentParser.Token.VALUE_NULL) { value = null; - type = "null"; + type = DataType.NULL; } else { - throw new XContentParseException(loc, "Failed to parse object: unexpected token [" + token + "] found"); - } - - currentParam = new TypedParamValue(type, value, false); - if ((previousParam != null && previousParam.hasExplicitType()) || result.isEmpty()) { - currentParam.tokenLocation(toProto(loc)); + errors.add(new XContentParseException(loc, token + " is not supported as a parameter")); } + currentParam = new QueryParam(null, value, type); + unNamedParams.add(currentParam); } - - result.add(currentParam); - previousParam = currentParam; } } - - return result; - } - - static ContentLocation toProto(org.elasticsearch.xcontent.XContentLocation toProto) { - if (toProto == null) { - return null; + if (namedParams.isEmpty() == false && unNamedParams.isEmpty() == false) { + errors.add( + new XContentParseException( + "Params cannot contain both named and unnamed parameters; got " + + Arrays.toString(namedParams.stream().map(QueryParam::nameValue).toArray()) + + " and " + + Arrays.toString(unNamedParams.stream().map(QueryParam::nameValue).toArray()) + ) + ); } - return new ContentLocation(toProto.lineNumber(), toProto.columnNumber()); - } - - static org.elasticsearch.xcontent.XContentLocation fromProto(ContentLocation fromProto) { - if (fromProto == null) { - return null; + if (errors.size() > 0) { + throw new XContentParseException( + "Failed to parse params: " + String.join("; ", errors.stream().map(ex -> ex.getMessage()).toArray(String[]::new)) + ); } - return new org.elasticsearch.xcontent.XContentLocation(fromProto.lineNumber, fromProto.columnNumber); + return new QueryParams(namedParams.isEmpty() ? unNamedParams : namedParams); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/AstBuilder.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/AstBuilder.java index 406b9e21e1d59..3b39e6a9d1fdb 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/AstBuilder.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/AstBuilder.java @@ -7,12 +7,8 @@ package org.elasticsearch.xpack.esql.parser; -import org.antlr.v4.runtime.Token; - -import java.util.Map; - public class AstBuilder extends LogicalPlanBuilder { - public AstBuilder(Map params) { + public AstBuilder(QueryParams params) { super(params); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ContentLocation.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ContentLocation.java deleted file mode 100644 index 6b1b50df32f5e..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/ContentLocation.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.parser; - -/** - * Light clone of XContentLocation - */ -public class ContentLocation { - - public static final ContentLocation UNKNOWN = new ContentLocation(-1, -1); - - public final int lineNumber; - public final int columnNumber; - - public ContentLocation(int lineNumber, int columnNumber) { - super(); - this.lineNumber = lineNumber; - this.columnNumber = columnNumber; - } - - @Override - public String toString() { - return lineNumber + ":" + columnNumber; - } -} 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 6f9e20e95430b..eb3689d0900d3 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 @@ -68,6 +68,7 @@ null '/' '%' null +null ']' null null @@ -193,6 +194,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -331,6 +333,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -464,4 +467,4 @@ METRICS_MODE CLOSING_METRICS_MODE atn: -[4, 0, 123, 1404, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 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, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 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, 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, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 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, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 4, 20, 565, 8, 20, 11, 20, 12, 20, 566, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 575, 8, 21, 10, 21, 12, 21, 578, 9, 21, 1, 21, 3, 21, 581, 8, 21, 1, 21, 3, 21, 584, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 593, 8, 22, 10, 22, 12, 22, 596, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 4, 23, 604, 8, 23, 11, 23, 12, 23, 605, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 3, 24, 613, 8, 24, 1, 25, 4, 25, 616, 8, 25, 11, 25, 12, 25, 617, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 657, 8, 36, 1, 36, 4, 36, 660, 8, 36, 11, 36, 12, 36, 661, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 3, 39, 671, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 3, 41, 678, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, 683, 8, 42, 10, 42, 12, 42, 686, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 694, 8, 42, 10, 42, 12, 42, 697, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 704, 8, 42, 1, 42, 3, 42, 707, 8, 42, 3, 42, 709, 8, 42, 1, 43, 4, 43, 712, 8, 43, 11, 43, 12, 43, 713, 1, 44, 4, 44, 717, 8, 44, 11, 44, 12, 44, 718, 1, 44, 1, 44, 5, 44, 723, 8, 44, 10, 44, 12, 44, 726, 9, 44, 1, 44, 1, 44, 4, 44, 730, 8, 44, 11, 44, 12, 44, 731, 1, 44, 4, 44, 735, 8, 44, 11, 44, 12, 44, 736, 1, 44, 1, 44, 5, 44, 741, 8, 44, 10, 44, 12, 44, 744, 9, 44, 3, 44, 746, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 752, 8, 44, 11, 44, 12, 44, 753, 1, 44, 1, 44, 3, 44, 758, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 5, 82, 889, 8, 82, 10, 82, 12, 82, 892, 9, 82, 1, 82, 1, 82, 3, 82, 896, 8, 82, 1, 82, 4, 82, 899, 8, 82, 11, 82, 12, 82, 900, 3, 82, 903, 8, 82, 1, 83, 1, 83, 4, 83, 907, 8, 83, 11, 83, 12, 83, 908, 1, 83, 1, 83, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 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, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 3, 102, 994, 8, 102, 1, 103, 1, 103, 3, 103, 998, 8, 103, 1, 103, 5, 103, 1001, 8, 103, 10, 103, 12, 103, 1004, 9, 103, 1, 103, 1, 103, 3, 103, 1008, 8, 103, 1, 103, 4, 103, 1011, 8, 103, 11, 103, 12, 103, 1012, 3, 103, 1015, 8, 103, 1, 104, 1, 104, 4, 104, 1019, 8, 104, 11, 104, 12, 104, 1020, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 122, 4, 122, 1096, 8, 122, 11, 122, 12, 122, 1097, 1, 122, 1, 122, 3, 122, 1102, 8, 122, 1, 122, 4, 122, 1105, 8, 122, 11, 122, 12, 122, 1106, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 4, 172, 1325, 8, 172, 11, 172, 12, 172, 1326, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 2, 594, 695, 0, 189, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 0, 66, 25, 68, 0, 70, 0, 72, 26, 74, 27, 76, 28, 78, 29, 80, 0, 82, 0, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 30, 102, 31, 104, 32, 106, 33, 108, 34, 110, 35, 112, 36, 114, 37, 116, 38, 118, 39, 120, 40, 122, 41, 124, 42, 126, 43, 128, 44, 130, 45, 132, 46, 134, 47, 136, 48, 138, 49, 140, 50, 142, 51, 144, 52, 146, 53, 148, 54, 150, 55, 152, 56, 154, 57, 156, 58, 158, 59, 160, 60, 162, 61, 164, 62, 166, 63, 168, 64, 170, 65, 172, 66, 174, 67, 176, 68, 178, 69, 180, 70, 182, 0, 184, 71, 186, 72, 188, 73, 190, 74, 192, 0, 194, 0, 196, 0, 198, 0, 200, 0, 202, 0, 204, 75, 206, 0, 208, 76, 210, 77, 212, 78, 214, 0, 216, 0, 218, 0, 220, 0, 222, 0, 224, 79, 226, 80, 228, 81, 230, 82, 232, 0, 234, 0, 236, 0, 238, 0, 240, 83, 242, 0, 244, 84, 246, 85, 248, 86, 250, 0, 252, 0, 254, 87, 256, 88, 258, 0, 260, 89, 262, 0, 264, 0, 266, 90, 268, 91, 270, 92, 272, 0, 274, 0, 276, 0, 278, 0, 280, 0, 282, 0, 284, 0, 286, 93, 288, 94, 290, 95, 292, 0, 294, 0, 296, 0, 298, 0, 300, 0, 302, 96, 304, 97, 306, 98, 308, 0, 310, 0, 312, 0, 314, 0, 316, 99, 318, 100, 320, 101, 322, 0, 324, 0, 326, 0, 328, 0, 330, 102, 332, 103, 334, 104, 336, 0, 338, 105, 340, 106, 342, 107, 344, 108, 346, 0, 348, 109, 350, 110, 352, 111, 354, 112, 356, 0, 358, 113, 360, 114, 362, 115, 364, 116, 366, 117, 368, 0, 370, 0, 372, 118, 374, 119, 376, 120, 378, 0, 380, 121, 382, 122, 384, 123, 386, 0, 388, 0, 390, 0, 392, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 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, 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, 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, 1, 0, 96, 96, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1427, 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, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 70, 1, 0, 0, 0, 1, 72, 1, 0, 0, 0, 1, 74, 1, 0, 0, 0, 1, 76, 1, 0, 0, 0, 2, 78, 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, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 170, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 2, 180, 1, 0, 0, 0, 2, 184, 1, 0, 0, 0, 2, 186, 1, 0, 0, 0, 2, 188, 1, 0, 0, 0, 2, 190, 1, 0, 0, 0, 3, 192, 1, 0, 0, 0, 3, 194, 1, 0, 0, 0, 3, 196, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 3, 204, 1, 0, 0, 0, 3, 206, 1, 0, 0, 0, 3, 208, 1, 0, 0, 0, 3, 210, 1, 0, 0, 0, 3, 212, 1, 0, 0, 0, 4, 214, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 224, 1, 0, 0, 0, 4, 226, 1, 0, 0, 0, 4, 228, 1, 0, 0, 0, 4, 230, 1, 0, 0, 0, 5, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 5, 240, 1, 0, 0, 0, 5, 242, 1, 0, 0, 0, 5, 244, 1, 0, 0, 0, 5, 246, 1, 0, 0, 0, 5, 248, 1, 0, 0, 0, 6, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 7, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 7, 282, 1, 0, 0, 0, 7, 284, 1, 0, 0, 0, 7, 286, 1, 0, 0, 0, 7, 288, 1, 0, 0, 0, 7, 290, 1, 0, 0, 0, 8, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 8, 296, 1, 0, 0, 0, 8, 298, 1, 0, 0, 0, 8, 300, 1, 0, 0, 0, 8, 302, 1, 0, 0, 0, 8, 304, 1, 0, 0, 0, 8, 306, 1, 0, 0, 0, 9, 308, 1, 0, 0, 0, 9, 310, 1, 0, 0, 0, 9, 312, 1, 0, 0, 0, 9, 314, 1, 0, 0, 0, 9, 316, 1, 0, 0, 0, 9, 318, 1, 0, 0, 0, 9, 320, 1, 0, 0, 0, 10, 322, 1, 0, 0, 0, 10, 324, 1, 0, 0, 0, 10, 326, 1, 0, 0, 0, 10, 328, 1, 0, 0, 0, 10, 330, 1, 0, 0, 0, 10, 332, 1, 0, 0, 0, 10, 334, 1, 0, 0, 0, 11, 336, 1, 0, 0, 0, 11, 338, 1, 0, 0, 0, 11, 340, 1, 0, 0, 0, 11, 342, 1, 0, 0, 0, 11, 344, 1, 0, 0, 0, 12, 346, 1, 0, 0, 0, 12, 348, 1, 0, 0, 0, 12, 350, 1, 0, 0, 0, 12, 352, 1, 0, 0, 0, 12, 354, 1, 0, 0, 0, 13, 356, 1, 0, 0, 0, 13, 358, 1, 0, 0, 0, 13, 360, 1, 0, 0, 0, 13, 362, 1, 0, 0, 0, 13, 364, 1, 0, 0, 0, 13, 366, 1, 0, 0, 0, 14, 368, 1, 0, 0, 0, 14, 370, 1, 0, 0, 0, 14, 372, 1, 0, 0, 0, 14, 374, 1, 0, 0, 0, 14, 376, 1, 0, 0, 0, 15, 378, 1, 0, 0, 0, 15, 380, 1, 0, 0, 0, 15, 382, 1, 0, 0, 0, 15, 384, 1, 0, 0, 0, 15, 386, 1, 0, 0, 0, 15, 388, 1, 0, 0, 0, 15, 390, 1, 0, 0, 0, 15, 392, 1, 0, 0, 0, 16, 394, 1, 0, 0, 0, 18, 404, 1, 0, 0, 0, 20, 411, 1, 0, 0, 0, 22, 420, 1, 0, 0, 0, 24, 427, 1, 0, 0, 0, 26, 437, 1, 0, 0, 0, 28, 444, 1, 0, 0, 0, 30, 451, 1, 0, 0, 0, 32, 465, 1, 0, 0, 0, 34, 472, 1, 0, 0, 0, 36, 480, 1, 0, 0, 0, 38, 489, 1, 0, 0, 0, 40, 496, 1, 0, 0, 0, 42, 506, 1, 0, 0, 0, 44, 518, 1, 0, 0, 0, 46, 527, 1, 0, 0, 0, 48, 533, 1, 0, 0, 0, 50, 540, 1, 0, 0, 0, 52, 547, 1, 0, 0, 0, 54, 555, 1, 0, 0, 0, 56, 564, 1, 0, 0, 0, 58, 570, 1, 0, 0, 0, 60, 587, 1, 0, 0, 0, 62, 603, 1, 0, 0, 0, 64, 612, 1, 0, 0, 0, 66, 615, 1, 0, 0, 0, 68, 619, 1, 0, 0, 0, 70, 624, 1, 0, 0, 0, 72, 629, 1, 0, 0, 0, 74, 633, 1, 0, 0, 0, 76, 637, 1, 0, 0, 0, 78, 641, 1, 0, 0, 0, 80, 645, 1, 0, 0, 0, 82, 647, 1, 0, 0, 0, 84, 649, 1, 0, 0, 0, 86, 652, 1, 0, 0, 0, 88, 654, 1, 0, 0, 0, 90, 663, 1, 0, 0, 0, 92, 665, 1, 0, 0, 0, 94, 670, 1, 0, 0, 0, 96, 672, 1, 0, 0, 0, 98, 677, 1, 0, 0, 0, 100, 708, 1, 0, 0, 0, 102, 711, 1, 0, 0, 0, 104, 757, 1, 0, 0, 0, 106, 759, 1, 0, 0, 0, 108, 762, 1, 0, 0, 0, 110, 766, 1, 0, 0, 0, 112, 770, 1, 0, 0, 0, 114, 772, 1, 0, 0, 0, 116, 775, 1, 0, 0, 0, 118, 777, 1, 0, 0, 0, 120, 782, 1, 0, 0, 0, 122, 784, 1, 0, 0, 0, 124, 790, 1, 0, 0, 0, 126, 796, 1, 0, 0, 0, 128, 801, 1, 0, 0, 0, 130, 803, 1, 0, 0, 0, 132, 806, 1, 0, 0, 0, 134, 809, 1, 0, 0, 0, 136, 814, 1, 0, 0, 0, 138, 818, 1, 0, 0, 0, 140, 823, 1, 0, 0, 0, 142, 829, 1, 0, 0, 0, 144, 832, 1, 0, 0, 0, 146, 834, 1, 0, 0, 0, 148, 840, 1, 0, 0, 0, 150, 842, 1, 0, 0, 0, 152, 847, 1, 0, 0, 0, 154, 850, 1, 0, 0, 0, 156, 853, 1, 0, 0, 0, 158, 856, 1, 0, 0, 0, 160, 858, 1, 0, 0, 0, 162, 861, 1, 0, 0, 0, 164, 863, 1, 0, 0, 0, 166, 866, 1, 0, 0, 0, 168, 868, 1, 0, 0, 0, 170, 870, 1, 0, 0, 0, 172, 872, 1, 0, 0, 0, 174, 874, 1, 0, 0, 0, 176, 876, 1, 0, 0, 0, 178, 881, 1, 0, 0, 0, 180, 902, 1, 0, 0, 0, 182, 904, 1, 0, 0, 0, 184, 912, 1, 0, 0, 0, 186, 914, 1, 0, 0, 0, 188, 918, 1, 0, 0, 0, 190, 922, 1, 0, 0, 0, 192, 926, 1, 0, 0, 0, 194, 931, 1, 0, 0, 0, 196, 935, 1, 0, 0, 0, 198, 939, 1, 0, 0, 0, 200, 943, 1, 0, 0, 0, 202, 947, 1, 0, 0, 0, 204, 951, 1, 0, 0, 0, 206, 960, 1, 0, 0, 0, 208, 964, 1, 0, 0, 0, 210, 968, 1, 0, 0, 0, 212, 972, 1, 0, 0, 0, 214, 976, 1, 0, 0, 0, 216, 981, 1, 0, 0, 0, 218, 985, 1, 0, 0, 0, 220, 993, 1, 0, 0, 0, 222, 1014, 1, 0, 0, 0, 224, 1018, 1, 0, 0, 0, 226, 1022, 1, 0, 0, 0, 228, 1026, 1, 0, 0, 0, 230, 1030, 1, 0, 0, 0, 232, 1034, 1, 0, 0, 0, 234, 1039, 1, 0, 0, 0, 236, 1043, 1, 0, 0, 0, 238, 1047, 1, 0, 0, 0, 240, 1051, 1, 0, 0, 0, 242, 1054, 1, 0, 0, 0, 244, 1058, 1, 0, 0, 0, 246, 1062, 1, 0, 0, 0, 248, 1066, 1, 0, 0, 0, 250, 1070, 1, 0, 0, 0, 252, 1075, 1, 0, 0, 0, 254, 1080, 1, 0, 0, 0, 256, 1085, 1, 0, 0, 0, 258, 1092, 1, 0, 0, 0, 260, 1101, 1, 0, 0, 0, 262, 1108, 1, 0, 0, 0, 264, 1112, 1, 0, 0, 0, 266, 1116, 1, 0, 0, 0, 268, 1120, 1, 0, 0, 0, 270, 1124, 1, 0, 0, 0, 272, 1128, 1, 0, 0, 0, 274, 1134, 1, 0, 0, 0, 276, 1138, 1, 0, 0, 0, 278, 1142, 1, 0, 0, 0, 280, 1146, 1, 0, 0, 0, 282, 1150, 1, 0, 0, 0, 284, 1154, 1, 0, 0, 0, 286, 1158, 1, 0, 0, 0, 288, 1162, 1, 0, 0, 0, 290, 1166, 1, 0, 0, 0, 292, 1170, 1, 0, 0, 0, 294, 1175, 1, 0, 0, 0, 296, 1179, 1, 0, 0, 0, 298, 1183, 1, 0, 0, 0, 300, 1188, 1, 0, 0, 0, 302, 1192, 1, 0, 0, 0, 304, 1196, 1, 0, 0, 0, 306, 1200, 1, 0, 0, 0, 308, 1204, 1, 0, 0, 0, 310, 1210, 1, 0, 0, 0, 312, 1214, 1, 0, 0, 0, 314, 1218, 1, 0, 0, 0, 316, 1222, 1, 0, 0, 0, 318, 1226, 1, 0, 0, 0, 320, 1230, 1, 0, 0, 0, 322, 1234, 1, 0, 0, 0, 324, 1239, 1, 0, 0, 0, 326, 1243, 1, 0, 0, 0, 328, 1247, 1, 0, 0, 0, 330, 1251, 1, 0, 0, 0, 332, 1255, 1, 0, 0, 0, 334, 1259, 1, 0, 0, 0, 336, 1263, 1, 0, 0, 0, 338, 1268, 1, 0, 0, 0, 340, 1273, 1, 0, 0, 0, 342, 1277, 1, 0, 0, 0, 344, 1281, 1, 0, 0, 0, 346, 1285, 1, 0, 0, 0, 348, 1290, 1, 0, 0, 0, 350, 1300, 1, 0, 0, 0, 352, 1304, 1, 0, 0, 0, 354, 1308, 1, 0, 0, 0, 356, 1312, 1, 0, 0, 0, 358, 1317, 1, 0, 0, 0, 360, 1324, 1, 0, 0, 0, 362, 1328, 1, 0, 0, 0, 364, 1332, 1, 0, 0, 0, 366, 1336, 1, 0, 0, 0, 368, 1340, 1, 0, 0, 0, 370, 1345, 1, 0, 0, 0, 372, 1351, 1, 0, 0, 0, 374, 1355, 1, 0, 0, 0, 376, 1359, 1, 0, 0, 0, 378, 1363, 1, 0, 0, 0, 380, 1369, 1, 0, 0, 0, 382, 1373, 1, 0, 0, 0, 384, 1377, 1, 0, 0, 0, 386, 1381, 1, 0, 0, 0, 388, 1387, 1, 0, 0, 0, 390, 1393, 1, 0, 0, 0, 392, 1399, 1, 0, 0, 0, 394, 395, 5, 100, 0, 0, 395, 396, 5, 105, 0, 0, 396, 397, 5, 115, 0, 0, 397, 398, 5, 115, 0, 0, 398, 399, 5, 101, 0, 0, 399, 400, 5, 99, 0, 0, 400, 401, 5, 116, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 6, 0, 0, 0, 403, 17, 1, 0, 0, 0, 404, 405, 5, 100, 0, 0, 405, 406, 5, 114, 0, 0, 406, 407, 5, 111, 0, 0, 407, 408, 5, 112, 0, 0, 408, 409, 1, 0, 0, 0, 409, 410, 6, 1, 1, 0, 410, 19, 1, 0, 0, 0, 411, 412, 5, 101, 0, 0, 412, 413, 5, 110, 0, 0, 413, 414, 5, 114, 0, 0, 414, 415, 5, 105, 0, 0, 415, 416, 5, 99, 0, 0, 416, 417, 5, 104, 0, 0, 417, 418, 1, 0, 0, 0, 418, 419, 6, 2, 2, 0, 419, 21, 1, 0, 0, 0, 420, 421, 5, 101, 0, 0, 421, 422, 5, 118, 0, 0, 422, 423, 5, 97, 0, 0, 423, 424, 5, 108, 0, 0, 424, 425, 1, 0, 0, 0, 425, 426, 6, 3, 0, 0, 426, 23, 1, 0, 0, 0, 427, 428, 5, 101, 0, 0, 428, 429, 5, 120, 0, 0, 429, 430, 5, 112, 0, 0, 430, 431, 5, 108, 0, 0, 431, 432, 5, 97, 0, 0, 432, 433, 5, 105, 0, 0, 433, 434, 5, 110, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 6, 4, 3, 0, 436, 25, 1, 0, 0, 0, 437, 438, 5, 102, 0, 0, 438, 439, 5, 114, 0, 0, 439, 440, 5, 111, 0, 0, 440, 441, 5, 109, 0, 0, 441, 442, 1, 0, 0, 0, 442, 443, 6, 5, 4, 0, 443, 27, 1, 0, 0, 0, 444, 445, 5, 103, 0, 0, 445, 446, 5, 114, 0, 0, 446, 447, 5, 111, 0, 0, 447, 448, 5, 107, 0, 0, 448, 449, 1, 0, 0, 0, 449, 450, 6, 6, 0, 0, 450, 29, 1, 0, 0, 0, 451, 452, 5, 105, 0, 0, 452, 453, 5, 110, 0, 0, 453, 454, 5, 108, 0, 0, 454, 455, 5, 105, 0, 0, 455, 456, 5, 110, 0, 0, 456, 457, 5, 101, 0, 0, 457, 458, 5, 115, 0, 0, 458, 459, 5, 116, 0, 0, 459, 460, 5, 97, 0, 0, 460, 461, 5, 116, 0, 0, 461, 462, 5, 115, 0, 0, 462, 463, 1, 0, 0, 0, 463, 464, 6, 7, 0, 0, 464, 31, 1, 0, 0, 0, 465, 466, 5, 107, 0, 0, 466, 467, 5, 101, 0, 0, 467, 468, 5, 101, 0, 0, 468, 469, 5, 112, 0, 0, 469, 470, 1, 0, 0, 0, 470, 471, 6, 8, 1, 0, 471, 33, 1, 0, 0, 0, 472, 473, 5, 108, 0, 0, 473, 474, 5, 105, 0, 0, 474, 475, 5, 109, 0, 0, 475, 476, 5, 105, 0, 0, 476, 477, 5, 116, 0, 0, 477, 478, 1, 0, 0, 0, 478, 479, 6, 9, 0, 0, 479, 35, 1, 0, 0, 0, 480, 481, 5, 108, 0, 0, 481, 482, 5, 111, 0, 0, 482, 483, 5, 111, 0, 0, 483, 484, 5, 107, 0, 0, 484, 485, 5, 117, 0, 0, 485, 486, 5, 112, 0, 0, 486, 487, 1, 0, 0, 0, 487, 488, 6, 10, 5, 0, 488, 37, 1, 0, 0, 0, 489, 490, 5, 109, 0, 0, 490, 491, 5, 101, 0, 0, 491, 492, 5, 116, 0, 0, 492, 493, 5, 97, 0, 0, 493, 494, 1, 0, 0, 0, 494, 495, 6, 11, 6, 0, 495, 39, 1, 0, 0, 0, 496, 497, 5, 109, 0, 0, 497, 498, 5, 101, 0, 0, 498, 499, 5, 116, 0, 0, 499, 500, 5, 114, 0, 0, 500, 501, 5, 105, 0, 0, 501, 502, 5, 99, 0, 0, 502, 503, 5, 115, 0, 0, 503, 504, 1, 0, 0, 0, 504, 505, 6, 12, 7, 0, 505, 41, 1, 0, 0, 0, 506, 507, 5, 109, 0, 0, 507, 508, 5, 118, 0, 0, 508, 509, 5, 95, 0, 0, 509, 510, 5, 101, 0, 0, 510, 511, 5, 120, 0, 0, 511, 512, 5, 112, 0, 0, 512, 513, 5, 97, 0, 0, 513, 514, 5, 110, 0, 0, 514, 515, 5, 100, 0, 0, 515, 516, 1, 0, 0, 0, 516, 517, 6, 13, 8, 0, 517, 43, 1, 0, 0, 0, 518, 519, 5, 114, 0, 0, 519, 520, 5, 101, 0, 0, 520, 521, 5, 110, 0, 0, 521, 522, 5, 97, 0, 0, 522, 523, 5, 109, 0, 0, 523, 524, 5, 101, 0, 0, 524, 525, 1, 0, 0, 0, 525, 526, 6, 14, 9, 0, 526, 45, 1, 0, 0, 0, 527, 528, 5, 114, 0, 0, 528, 529, 5, 111, 0, 0, 529, 530, 5, 119, 0, 0, 530, 531, 1, 0, 0, 0, 531, 532, 6, 15, 0, 0, 532, 47, 1, 0, 0, 0, 533, 534, 5, 115, 0, 0, 534, 535, 5, 104, 0, 0, 535, 536, 5, 111, 0, 0, 536, 537, 5, 119, 0, 0, 537, 538, 1, 0, 0, 0, 538, 539, 6, 16, 10, 0, 539, 49, 1, 0, 0, 0, 540, 541, 5, 115, 0, 0, 541, 542, 5, 111, 0, 0, 542, 543, 5, 114, 0, 0, 543, 544, 5, 116, 0, 0, 544, 545, 1, 0, 0, 0, 545, 546, 6, 17, 0, 0, 546, 51, 1, 0, 0, 0, 547, 548, 5, 115, 0, 0, 548, 549, 5, 116, 0, 0, 549, 550, 5, 97, 0, 0, 550, 551, 5, 116, 0, 0, 551, 552, 5, 115, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 6, 18, 0, 0, 554, 53, 1, 0, 0, 0, 555, 556, 5, 119, 0, 0, 556, 557, 5, 104, 0, 0, 557, 558, 5, 101, 0, 0, 558, 559, 5, 114, 0, 0, 559, 560, 5, 101, 0, 0, 560, 561, 1, 0, 0, 0, 561, 562, 6, 19, 0, 0, 562, 55, 1, 0, 0, 0, 563, 565, 8, 0, 0, 0, 564, 563, 1, 0, 0, 0, 565, 566, 1, 0, 0, 0, 566, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 6, 20, 0, 0, 569, 57, 1, 0, 0, 0, 570, 571, 5, 47, 0, 0, 571, 572, 5, 47, 0, 0, 572, 576, 1, 0, 0, 0, 573, 575, 8, 1, 0, 0, 574, 573, 1, 0, 0, 0, 575, 578, 1, 0, 0, 0, 576, 574, 1, 0, 0, 0, 576, 577, 1, 0, 0, 0, 577, 580, 1, 0, 0, 0, 578, 576, 1, 0, 0, 0, 579, 581, 5, 13, 0, 0, 580, 579, 1, 0, 0, 0, 580, 581, 1, 0, 0, 0, 581, 583, 1, 0, 0, 0, 582, 584, 5, 10, 0, 0, 583, 582, 1, 0, 0, 0, 583, 584, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 586, 6, 21, 11, 0, 586, 59, 1, 0, 0, 0, 587, 588, 5, 47, 0, 0, 588, 589, 5, 42, 0, 0, 589, 594, 1, 0, 0, 0, 590, 593, 3, 60, 22, 0, 591, 593, 9, 0, 0, 0, 592, 590, 1, 0, 0, 0, 592, 591, 1, 0, 0, 0, 593, 596, 1, 0, 0, 0, 594, 595, 1, 0, 0, 0, 594, 592, 1, 0, 0, 0, 595, 597, 1, 0, 0, 0, 596, 594, 1, 0, 0, 0, 597, 598, 5, 42, 0, 0, 598, 599, 5, 47, 0, 0, 599, 600, 1, 0, 0, 0, 600, 601, 6, 22, 11, 0, 601, 61, 1, 0, 0, 0, 602, 604, 7, 2, 0, 0, 603, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 603, 1, 0, 0, 0, 605, 606, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 6, 23, 11, 0, 608, 63, 1, 0, 0, 0, 609, 613, 8, 3, 0, 0, 610, 611, 5, 47, 0, 0, 611, 613, 8, 4, 0, 0, 612, 609, 1, 0, 0, 0, 612, 610, 1, 0, 0, 0, 613, 65, 1, 0, 0, 0, 614, 616, 3, 64, 24, 0, 615, 614, 1, 0, 0, 0, 616, 617, 1, 0, 0, 0, 617, 615, 1, 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 67, 1, 0, 0, 0, 619, 620, 3, 176, 80, 0, 620, 621, 1, 0, 0, 0, 621, 622, 6, 26, 12, 0, 622, 623, 6, 26, 13, 0, 623, 69, 1, 0, 0, 0, 624, 625, 3, 78, 31, 0, 625, 626, 1, 0, 0, 0, 626, 627, 6, 27, 14, 0, 627, 628, 6, 27, 15, 0, 628, 71, 1, 0, 0, 0, 629, 630, 3, 62, 23, 0, 630, 631, 1, 0, 0, 0, 631, 632, 6, 28, 11, 0, 632, 73, 1, 0, 0, 0, 633, 634, 3, 58, 21, 0, 634, 635, 1, 0, 0, 0, 635, 636, 6, 29, 11, 0, 636, 75, 1, 0, 0, 0, 637, 638, 3, 60, 22, 0, 638, 639, 1, 0, 0, 0, 639, 640, 6, 30, 11, 0, 640, 77, 1, 0, 0, 0, 641, 642, 5, 124, 0, 0, 642, 643, 1, 0, 0, 0, 643, 644, 6, 31, 15, 0, 644, 79, 1, 0, 0, 0, 645, 646, 7, 5, 0, 0, 646, 81, 1, 0, 0, 0, 647, 648, 7, 6, 0, 0, 648, 83, 1, 0, 0, 0, 649, 650, 5, 92, 0, 0, 650, 651, 7, 7, 0, 0, 651, 85, 1, 0, 0, 0, 652, 653, 8, 8, 0, 0, 653, 87, 1, 0, 0, 0, 654, 656, 7, 9, 0, 0, 655, 657, 7, 10, 0, 0, 656, 655, 1, 0, 0, 0, 656, 657, 1, 0, 0, 0, 657, 659, 1, 0, 0, 0, 658, 660, 3, 80, 32, 0, 659, 658, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 89, 1, 0, 0, 0, 663, 664, 5, 64, 0, 0, 664, 91, 1, 0, 0, 0, 665, 666, 5, 96, 0, 0, 666, 93, 1, 0, 0, 0, 667, 671, 8, 11, 0, 0, 668, 669, 5, 96, 0, 0, 669, 671, 5, 96, 0, 0, 670, 667, 1, 0, 0, 0, 670, 668, 1, 0, 0, 0, 671, 95, 1, 0, 0, 0, 672, 673, 5, 95, 0, 0, 673, 97, 1, 0, 0, 0, 674, 678, 3, 82, 33, 0, 675, 678, 3, 80, 32, 0, 676, 678, 3, 96, 40, 0, 677, 674, 1, 0, 0, 0, 677, 675, 1, 0, 0, 0, 677, 676, 1, 0, 0, 0, 678, 99, 1, 0, 0, 0, 679, 684, 5, 34, 0, 0, 680, 683, 3, 84, 34, 0, 681, 683, 3, 86, 35, 0, 682, 680, 1, 0, 0, 0, 682, 681, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 687, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 709, 5, 34, 0, 0, 688, 689, 5, 34, 0, 0, 689, 690, 5, 34, 0, 0, 690, 691, 5, 34, 0, 0, 691, 695, 1, 0, 0, 0, 692, 694, 8, 1, 0, 0, 693, 692, 1, 0, 0, 0, 694, 697, 1, 0, 0, 0, 695, 696, 1, 0, 0, 0, 695, 693, 1, 0, 0, 0, 696, 698, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 698, 699, 5, 34, 0, 0, 699, 700, 5, 34, 0, 0, 700, 701, 5, 34, 0, 0, 701, 703, 1, 0, 0, 0, 702, 704, 5, 34, 0, 0, 703, 702, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 704, 706, 1, 0, 0, 0, 705, 707, 5, 34, 0, 0, 706, 705, 1, 0, 0, 0, 706, 707, 1, 0, 0, 0, 707, 709, 1, 0, 0, 0, 708, 679, 1, 0, 0, 0, 708, 688, 1, 0, 0, 0, 709, 101, 1, 0, 0, 0, 710, 712, 3, 80, 32, 0, 711, 710, 1, 0, 0, 0, 712, 713, 1, 0, 0, 0, 713, 711, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 103, 1, 0, 0, 0, 715, 717, 3, 80, 32, 0, 716, 715, 1, 0, 0, 0, 717, 718, 1, 0, 0, 0, 718, 716, 1, 0, 0, 0, 718, 719, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 724, 3, 120, 52, 0, 721, 723, 3, 80, 32, 0, 722, 721, 1, 0, 0, 0, 723, 726, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0, 0, 0, 725, 758, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 727, 729, 3, 120, 52, 0, 728, 730, 3, 80, 32, 0, 729, 728, 1, 0, 0, 0, 730, 731, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 758, 1, 0, 0, 0, 733, 735, 3, 80, 32, 0, 734, 733, 1, 0, 0, 0, 735, 736, 1, 0, 0, 0, 736, 734, 1, 0, 0, 0, 736, 737, 1, 0, 0, 0, 737, 745, 1, 0, 0, 0, 738, 742, 3, 120, 52, 0, 739, 741, 3, 80, 32, 0, 740, 739, 1, 0, 0, 0, 741, 744, 1, 0, 0, 0, 742, 740, 1, 0, 0, 0, 742, 743, 1, 0, 0, 0, 743, 746, 1, 0, 0, 0, 744, 742, 1, 0, 0, 0, 745, 738, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 3, 88, 36, 0, 748, 758, 1, 0, 0, 0, 749, 751, 3, 120, 52, 0, 750, 752, 3, 80, 32, 0, 751, 750, 1, 0, 0, 0, 752, 753, 1, 0, 0, 0, 753, 751, 1, 0, 0, 0, 753, 754, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 756, 3, 88, 36, 0, 756, 758, 1, 0, 0, 0, 757, 716, 1, 0, 0, 0, 757, 727, 1, 0, 0, 0, 757, 734, 1, 0, 0, 0, 757, 749, 1, 0, 0, 0, 758, 105, 1, 0, 0, 0, 759, 760, 5, 98, 0, 0, 760, 761, 5, 121, 0, 0, 761, 107, 1, 0, 0, 0, 762, 763, 5, 97, 0, 0, 763, 764, 5, 110, 0, 0, 764, 765, 5, 100, 0, 0, 765, 109, 1, 0, 0, 0, 766, 767, 5, 97, 0, 0, 767, 768, 5, 115, 0, 0, 768, 769, 5, 99, 0, 0, 769, 111, 1, 0, 0, 0, 770, 771, 5, 61, 0, 0, 771, 113, 1, 0, 0, 0, 772, 773, 5, 58, 0, 0, 773, 774, 5, 58, 0, 0, 774, 115, 1, 0, 0, 0, 775, 776, 5, 44, 0, 0, 776, 117, 1, 0, 0, 0, 777, 778, 5, 100, 0, 0, 778, 779, 5, 101, 0, 0, 779, 780, 5, 115, 0, 0, 780, 781, 5, 99, 0, 0, 781, 119, 1, 0, 0, 0, 782, 783, 5, 46, 0, 0, 783, 121, 1, 0, 0, 0, 784, 785, 5, 102, 0, 0, 785, 786, 5, 97, 0, 0, 786, 787, 5, 108, 0, 0, 787, 788, 5, 115, 0, 0, 788, 789, 5, 101, 0, 0, 789, 123, 1, 0, 0, 0, 790, 791, 5, 102, 0, 0, 791, 792, 5, 105, 0, 0, 792, 793, 5, 114, 0, 0, 793, 794, 5, 115, 0, 0, 794, 795, 5, 116, 0, 0, 795, 125, 1, 0, 0, 0, 796, 797, 5, 108, 0, 0, 797, 798, 5, 97, 0, 0, 798, 799, 5, 115, 0, 0, 799, 800, 5, 116, 0, 0, 800, 127, 1, 0, 0, 0, 801, 802, 5, 40, 0, 0, 802, 129, 1, 0, 0, 0, 803, 804, 5, 105, 0, 0, 804, 805, 5, 110, 0, 0, 805, 131, 1, 0, 0, 0, 806, 807, 5, 105, 0, 0, 807, 808, 5, 115, 0, 0, 808, 133, 1, 0, 0, 0, 809, 810, 5, 108, 0, 0, 810, 811, 5, 105, 0, 0, 811, 812, 5, 107, 0, 0, 812, 813, 5, 101, 0, 0, 813, 135, 1, 0, 0, 0, 814, 815, 5, 110, 0, 0, 815, 816, 5, 111, 0, 0, 816, 817, 5, 116, 0, 0, 817, 137, 1, 0, 0, 0, 818, 819, 5, 110, 0, 0, 819, 820, 5, 117, 0, 0, 820, 821, 5, 108, 0, 0, 821, 822, 5, 108, 0, 0, 822, 139, 1, 0, 0, 0, 823, 824, 5, 110, 0, 0, 824, 825, 5, 117, 0, 0, 825, 826, 5, 108, 0, 0, 826, 827, 5, 108, 0, 0, 827, 828, 5, 115, 0, 0, 828, 141, 1, 0, 0, 0, 829, 830, 5, 111, 0, 0, 830, 831, 5, 114, 0, 0, 831, 143, 1, 0, 0, 0, 832, 833, 5, 63, 0, 0, 833, 145, 1, 0, 0, 0, 834, 835, 5, 114, 0, 0, 835, 836, 5, 108, 0, 0, 836, 837, 5, 105, 0, 0, 837, 838, 5, 107, 0, 0, 838, 839, 5, 101, 0, 0, 839, 147, 1, 0, 0, 0, 840, 841, 5, 41, 0, 0, 841, 149, 1, 0, 0, 0, 842, 843, 5, 116, 0, 0, 843, 844, 5, 114, 0, 0, 844, 845, 5, 117, 0, 0, 845, 846, 5, 101, 0, 0, 846, 151, 1, 0, 0, 0, 847, 848, 5, 61, 0, 0, 848, 849, 5, 61, 0, 0, 849, 153, 1, 0, 0, 0, 850, 851, 5, 61, 0, 0, 851, 852, 5, 126, 0, 0, 852, 155, 1, 0, 0, 0, 853, 854, 5, 33, 0, 0, 854, 855, 5, 61, 0, 0, 855, 157, 1, 0, 0, 0, 856, 857, 5, 60, 0, 0, 857, 159, 1, 0, 0, 0, 858, 859, 5, 60, 0, 0, 859, 860, 5, 61, 0, 0, 860, 161, 1, 0, 0, 0, 861, 862, 5, 62, 0, 0, 862, 163, 1, 0, 0, 0, 863, 864, 5, 62, 0, 0, 864, 865, 5, 61, 0, 0, 865, 165, 1, 0, 0, 0, 866, 867, 5, 43, 0, 0, 867, 167, 1, 0, 0, 0, 868, 869, 5, 45, 0, 0, 869, 169, 1, 0, 0, 0, 870, 871, 5, 42, 0, 0, 871, 171, 1, 0, 0, 0, 872, 873, 5, 47, 0, 0, 873, 173, 1, 0, 0, 0, 874, 875, 5, 37, 0, 0, 875, 175, 1, 0, 0, 0, 876, 877, 5, 91, 0, 0, 877, 878, 1, 0, 0, 0, 878, 879, 6, 80, 0, 0, 879, 880, 6, 80, 0, 0, 880, 177, 1, 0, 0, 0, 881, 882, 5, 93, 0, 0, 882, 883, 1, 0, 0, 0, 883, 884, 6, 81, 15, 0, 884, 885, 6, 81, 15, 0, 885, 179, 1, 0, 0, 0, 886, 890, 3, 82, 33, 0, 887, 889, 3, 98, 41, 0, 888, 887, 1, 0, 0, 0, 889, 892, 1, 0, 0, 0, 890, 888, 1, 0, 0, 0, 890, 891, 1, 0, 0, 0, 891, 903, 1, 0, 0, 0, 892, 890, 1, 0, 0, 0, 893, 896, 3, 96, 40, 0, 894, 896, 3, 90, 37, 0, 895, 893, 1, 0, 0, 0, 895, 894, 1, 0, 0, 0, 896, 898, 1, 0, 0, 0, 897, 899, 3, 98, 41, 0, 898, 897, 1, 0, 0, 0, 899, 900, 1, 0, 0, 0, 900, 898, 1, 0, 0, 0, 900, 901, 1, 0, 0, 0, 901, 903, 1, 0, 0, 0, 902, 886, 1, 0, 0, 0, 902, 895, 1, 0, 0, 0, 903, 181, 1, 0, 0, 0, 904, 906, 3, 92, 38, 0, 905, 907, 3, 94, 39, 0, 906, 905, 1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 910, 1, 0, 0, 0, 910, 911, 3, 92, 38, 0, 911, 183, 1, 0, 0, 0, 912, 913, 3, 182, 83, 0, 913, 185, 1, 0, 0, 0, 914, 915, 3, 58, 21, 0, 915, 916, 1, 0, 0, 0, 916, 917, 6, 85, 11, 0, 917, 187, 1, 0, 0, 0, 918, 919, 3, 60, 22, 0, 919, 920, 1, 0, 0, 0, 920, 921, 6, 86, 11, 0, 921, 189, 1, 0, 0, 0, 922, 923, 3, 62, 23, 0, 923, 924, 1, 0, 0, 0, 924, 925, 6, 87, 11, 0, 925, 191, 1, 0, 0, 0, 926, 927, 3, 78, 31, 0, 927, 928, 1, 0, 0, 0, 928, 929, 6, 88, 14, 0, 929, 930, 6, 88, 15, 0, 930, 193, 1, 0, 0, 0, 931, 932, 3, 176, 80, 0, 932, 933, 1, 0, 0, 0, 933, 934, 6, 89, 12, 0, 934, 195, 1, 0, 0, 0, 935, 936, 3, 178, 81, 0, 936, 937, 1, 0, 0, 0, 937, 938, 6, 90, 16, 0, 938, 197, 1, 0, 0, 0, 939, 940, 3, 116, 50, 0, 940, 941, 1, 0, 0, 0, 941, 942, 6, 91, 17, 0, 942, 199, 1, 0, 0, 0, 943, 944, 3, 112, 48, 0, 944, 945, 1, 0, 0, 0, 945, 946, 6, 92, 18, 0, 946, 201, 1, 0, 0, 0, 947, 948, 3, 100, 42, 0, 948, 949, 1, 0, 0, 0, 949, 950, 6, 93, 19, 0, 950, 203, 1, 0, 0, 0, 951, 952, 5, 109, 0, 0, 952, 953, 5, 101, 0, 0, 953, 954, 5, 116, 0, 0, 954, 955, 5, 97, 0, 0, 955, 956, 5, 100, 0, 0, 956, 957, 5, 97, 0, 0, 957, 958, 5, 116, 0, 0, 958, 959, 5, 97, 0, 0, 959, 205, 1, 0, 0, 0, 960, 961, 3, 66, 25, 0, 961, 962, 1, 0, 0, 0, 962, 963, 6, 95, 20, 0, 963, 207, 1, 0, 0, 0, 964, 965, 3, 58, 21, 0, 965, 966, 1, 0, 0, 0, 966, 967, 6, 96, 11, 0, 967, 209, 1, 0, 0, 0, 968, 969, 3, 60, 22, 0, 969, 970, 1, 0, 0, 0, 970, 971, 6, 97, 11, 0, 971, 211, 1, 0, 0, 0, 972, 973, 3, 62, 23, 0, 973, 974, 1, 0, 0, 0, 974, 975, 6, 98, 11, 0, 975, 213, 1, 0, 0, 0, 976, 977, 3, 78, 31, 0, 977, 978, 1, 0, 0, 0, 978, 979, 6, 99, 14, 0, 979, 980, 6, 99, 15, 0, 980, 215, 1, 0, 0, 0, 981, 982, 3, 120, 52, 0, 982, 983, 1, 0, 0, 0, 983, 984, 6, 100, 21, 0, 984, 217, 1, 0, 0, 0, 985, 986, 3, 116, 50, 0, 986, 987, 1, 0, 0, 0, 987, 988, 6, 101, 17, 0, 988, 219, 1, 0, 0, 0, 989, 994, 3, 82, 33, 0, 990, 994, 3, 80, 32, 0, 991, 994, 3, 96, 40, 0, 992, 994, 3, 170, 77, 0, 993, 989, 1, 0, 0, 0, 993, 990, 1, 0, 0, 0, 993, 991, 1, 0, 0, 0, 993, 992, 1, 0, 0, 0, 994, 221, 1, 0, 0, 0, 995, 998, 3, 82, 33, 0, 996, 998, 3, 170, 77, 0, 997, 995, 1, 0, 0, 0, 997, 996, 1, 0, 0, 0, 998, 1002, 1, 0, 0, 0, 999, 1001, 3, 220, 102, 0, 1000, 999, 1, 0, 0, 0, 1001, 1004, 1, 0, 0, 0, 1002, 1000, 1, 0, 0, 0, 1002, 1003, 1, 0, 0, 0, 1003, 1015, 1, 0, 0, 0, 1004, 1002, 1, 0, 0, 0, 1005, 1008, 3, 96, 40, 0, 1006, 1008, 3, 90, 37, 0, 1007, 1005, 1, 0, 0, 0, 1007, 1006, 1, 0, 0, 0, 1008, 1010, 1, 0, 0, 0, 1009, 1011, 3, 220, 102, 0, 1010, 1009, 1, 0, 0, 0, 1011, 1012, 1, 0, 0, 0, 1012, 1010, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1015, 1, 0, 0, 0, 1014, 997, 1, 0, 0, 0, 1014, 1007, 1, 0, 0, 0, 1015, 223, 1, 0, 0, 0, 1016, 1019, 3, 222, 103, 0, 1017, 1019, 3, 182, 83, 0, 1018, 1016, 1, 0, 0, 0, 1018, 1017, 1, 0, 0, 0, 1019, 1020, 1, 0, 0, 0, 1020, 1018, 1, 0, 0, 0, 1020, 1021, 1, 0, 0, 0, 1021, 225, 1, 0, 0, 0, 1022, 1023, 3, 58, 21, 0, 1023, 1024, 1, 0, 0, 0, 1024, 1025, 6, 105, 11, 0, 1025, 227, 1, 0, 0, 0, 1026, 1027, 3, 60, 22, 0, 1027, 1028, 1, 0, 0, 0, 1028, 1029, 6, 106, 11, 0, 1029, 229, 1, 0, 0, 0, 1030, 1031, 3, 62, 23, 0, 1031, 1032, 1, 0, 0, 0, 1032, 1033, 6, 107, 11, 0, 1033, 231, 1, 0, 0, 0, 1034, 1035, 3, 78, 31, 0, 1035, 1036, 1, 0, 0, 0, 1036, 1037, 6, 108, 14, 0, 1037, 1038, 6, 108, 15, 0, 1038, 233, 1, 0, 0, 0, 1039, 1040, 3, 112, 48, 0, 1040, 1041, 1, 0, 0, 0, 1041, 1042, 6, 109, 18, 0, 1042, 235, 1, 0, 0, 0, 1043, 1044, 3, 116, 50, 0, 1044, 1045, 1, 0, 0, 0, 1045, 1046, 6, 110, 17, 0, 1046, 237, 1, 0, 0, 0, 1047, 1048, 3, 120, 52, 0, 1048, 1049, 1, 0, 0, 0, 1049, 1050, 6, 111, 21, 0, 1050, 239, 1, 0, 0, 0, 1051, 1052, 5, 97, 0, 0, 1052, 1053, 5, 115, 0, 0, 1053, 241, 1, 0, 0, 0, 1054, 1055, 3, 224, 104, 0, 1055, 1056, 1, 0, 0, 0, 1056, 1057, 6, 113, 22, 0, 1057, 243, 1, 0, 0, 0, 1058, 1059, 3, 58, 21, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1061, 6, 114, 11, 0, 1061, 245, 1, 0, 0, 0, 1062, 1063, 3, 60, 22, 0, 1063, 1064, 1, 0, 0, 0, 1064, 1065, 6, 115, 11, 0, 1065, 247, 1, 0, 0, 0, 1066, 1067, 3, 62, 23, 0, 1067, 1068, 1, 0, 0, 0, 1068, 1069, 6, 116, 11, 0, 1069, 249, 1, 0, 0, 0, 1070, 1071, 3, 78, 31, 0, 1071, 1072, 1, 0, 0, 0, 1072, 1073, 6, 117, 14, 0, 1073, 1074, 6, 117, 15, 0, 1074, 251, 1, 0, 0, 0, 1075, 1076, 3, 176, 80, 0, 1076, 1077, 1, 0, 0, 0, 1077, 1078, 6, 118, 12, 0, 1078, 1079, 6, 118, 23, 0, 1079, 253, 1, 0, 0, 0, 1080, 1081, 5, 111, 0, 0, 1081, 1082, 5, 110, 0, 0, 1082, 1083, 1, 0, 0, 0, 1083, 1084, 6, 119, 24, 0, 1084, 255, 1, 0, 0, 0, 1085, 1086, 5, 119, 0, 0, 1086, 1087, 5, 105, 0, 0, 1087, 1088, 5, 116, 0, 0, 1088, 1089, 5, 104, 0, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1091, 6, 120, 24, 0, 1091, 257, 1, 0, 0, 0, 1092, 1093, 8, 12, 0, 0, 1093, 259, 1, 0, 0, 0, 1094, 1096, 3, 258, 121, 0, 1095, 1094, 1, 0, 0, 0, 1096, 1097, 1, 0, 0, 0, 1097, 1095, 1, 0, 0, 0, 1097, 1098, 1, 0, 0, 0, 1098, 1099, 1, 0, 0, 0, 1099, 1100, 3, 358, 171, 0, 1100, 1102, 1, 0, 0, 0, 1101, 1095, 1, 0, 0, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1104, 1, 0, 0, 0, 1103, 1105, 3, 258, 121, 0, 1104, 1103, 1, 0, 0, 0, 1105, 1106, 1, 0, 0, 0, 1106, 1104, 1, 0, 0, 0, 1106, 1107, 1, 0, 0, 0, 1107, 261, 1, 0, 0, 0, 1108, 1109, 3, 184, 84, 0, 1109, 1110, 1, 0, 0, 0, 1110, 1111, 6, 123, 25, 0, 1111, 263, 1, 0, 0, 0, 1112, 1113, 3, 260, 122, 0, 1113, 1114, 1, 0, 0, 0, 1114, 1115, 6, 124, 26, 0, 1115, 265, 1, 0, 0, 0, 1116, 1117, 3, 58, 21, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1119, 6, 125, 11, 0, 1119, 267, 1, 0, 0, 0, 1120, 1121, 3, 60, 22, 0, 1121, 1122, 1, 0, 0, 0, 1122, 1123, 6, 126, 11, 0, 1123, 269, 1, 0, 0, 0, 1124, 1125, 3, 62, 23, 0, 1125, 1126, 1, 0, 0, 0, 1126, 1127, 6, 127, 11, 0, 1127, 271, 1, 0, 0, 0, 1128, 1129, 3, 78, 31, 0, 1129, 1130, 1, 0, 0, 0, 1130, 1131, 6, 128, 14, 0, 1131, 1132, 6, 128, 15, 0, 1132, 1133, 6, 128, 15, 0, 1133, 273, 1, 0, 0, 0, 1134, 1135, 3, 112, 48, 0, 1135, 1136, 1, 0, 0, 0, 1136, 1137, 6, 129, 18, 0, 1137, 275, 1, 0, 0, 0, 1138, 1139, 3, 116, 50, 0, 1139, 1140, 1, 0, 0, 0, 1140, 1141, 6, 130, 17, 0, 1141, 277, 1, 0, 0, 0, 1142, 1143, 3, 120, 52, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1145, 6, 131, 21, 0, 1145, 279, 1, 0, 0, 0, 1146, 1147, 3, 256, 120, 0, 1147, 1148, 1, 0, 0, 0, 1148, 1149, 6, 132, 27, 0, 1149, 281, 1, 0, 0, 0, 1150, 1151, 3, 224, 104, 0, 1151, 1152, 1, 0, 0, 0, 1152, 1153, 6, 133, 22, 0, 1153, 283, 1, 0, 0, 0, 1154, 1155, 3, 184, 84, 0, 1155, 1156, 1, 0, 0, 0, 1156, 1157, 6, 134, 25, 0, 1157, 285, 1, 0, 0, 0, 1158, 1159, 3, 58, 21, 0, 1159, 1160, 1, 0, 0, 0, 1160, 1161, 6, 135, 11, 0, 1161, 287, 1, 0, 0, 0, 1162, 1163, 3, 60, 22, 0, 1163, 1164, 1, 0, 0, 0, 1164, 1165, 6, 136, 11, 0, 1165, 289, 1, 0, 0, 0, 1166, 1167, 3, 62, 23, 0, 1167, 1168, 1, 0, 0, 0, 1168, 1169, 6, 137, 11, 0, 1169, 291, 1, 0, 0, 0, 1170, 1171, 3, 78, 31, 0, 1171, 1172, 1, 0, 0, 0, 1172, 1173, 6, 138, 14, 0, 1173, 1174, 6, 138, 15, 0, 1174, 293, 1, 0, 0, 0, 1175, 1176, 3, 116, 50, 0, 1176, 1177, 1, 0, 0, 0, 1177, 1178, 6, 139, 17, 0, 1178, 295, 1, 0, 0, 0, 1179, 1180, 3, 120, 52, 0, 1180, 1181, 1, 0, 0, 0, 1181, 1182, 6, 140, 21, 0, 1182, 297, 1, 0, 0, 0, 1183, 1184, 3, 254, 119, 0, 1184, 1185, 1, 0, 0, 0, 1185, 1186, 6, 141, 28, 0, 1186, 1187, 6, 141, 29, 0, 1187, 299, 1, 0, 0, 0, 1188, 1189, 3, 66, 25, 0, 1189, 1190, 1, 0, 0, 0, 1190, 1191, 6, 142, 20, 0, 1191, 301, 1, 0, 0, 0, 1192, 1193, 3, 58, 21, 0, 1193, 1194, 1, 0, 0, 0, 1194, 1195, 6, 143, 11, 0, 1195, 303, 1, 0, 0, 0, 1196, 1197, 3, 60, 22, 0, 1197, 1198, 1, 0, 0, 0, 1198, 1199, 6, 144, 11, 0, 1199, 305, 1, 0, 0, 0, 1200, 1201, 3, 62, 23, 0, 1201, 1202, 1, 0, 0, 0, 1202, 1203, 6, 145, 11, 0, 1203, 307, 1, 0, 0, 0, 1204, 1205, 3, 78, 31, 0, 1205, 1206, 1, 0, 0, 0, 1206, 1207, 6, 146, 14, 0, 1207, 1208, 6, 146, 15, 0, 1208, 1209, 6, 146, 15, 0, 1209, 309, 1, 0, 0, 0, 1210, 1211, 3, 116, 50, 0, 1211, 1212, 1, 0, 0, 0, 1212, 1213, 6, 147, 17, 0, 1213, 311, 1, 0, 0, 0, 1214, 1215, 3, 120, 52, 0, 1215, 1216, 1, 0, 0, 0, 1216, 1217, 6, 148, 21, 0, 1217, 313, 1, 0, 0, 0, 1218, 1219, 3, 224, 104, 0, 1219, 1220, 1, 0, 0, 0, 1220, 1221, 6, 149, 22, 0, 1221, 315, 1, 0, 0, 0, 1222, 1223, 3, 58, 21, 0, 1223, 1224, 1, 0, 0, 0, 1224, 1225, 6, 150, 11, 0, 1225, 317, 1, 0, 0, 0, 1226, 1227, 3, 60, 22, 0, 1227, 1228, 1, 0, 0, 0, 1228, 1229, 6, 151, 11, 0, 1229, 319, 1, 0, 0, 0, 1230, 1231, 3, 62, 23, 0, 1231, 1232, 1, 0, 0, 0, 1232, 1233, 6, 152, 11, 0, 1233, 321, 1, 0, 0, 0, 1234, 1235, 3, 78, 31, 0, 1235, 1236, 1, 0, 0, 0, 1236, 1237, 6, 153, 14, 0, 1237, 1238, 6, 153, 15, 0, 1238, 323, 1, 0, 0, 0, 1239, 1240, 3, 120, 52, 0, 1240, 1241, 1, 0, 0, 0, 1241, 1242, 6, 154, 21, 0, 1242, 325, 1, 0, 0, 0, 1243, 1244, 3, 184, 84, 0, 1244, 1245, 1, 0, 0, 0, 1245, 1246, 6, 155, 25, 0, 1246, 327, 1, 0, 0, 0, 1247, 1248, 3, 180, 82, 0, 1248, 1249, 1, 0, 0, 0, 1249, 1250, 6, 156, 30, 0, 1250, 329, 1, 0, 0, 0, 1251, 1252, 3, 58, 21, 0, 1252, 1253, 1, 0, 0, 0, 1253, 1254, 6, 157, 11, 0, 1254, 331, 1, 0, 0, 0, 1255, 1256, 3, 60, 22, 0, 1256, 1257, 1, 0, 0, 0, 1257, 1258, 6, 158, 11, 0, 1258, 333, 1, 0, 0, 0, 1259, 1260, 3, 62, 23, 0, 1260, 1261, 1, 0, 0, 0, 1261, 1262, 6, 159, 11, 0, 1262, 335, 1, 0, 0, 0, 1263, 1264, 3, 78, 31, 0, 1264, 1265, 1, 0, 0, 0, 1265, 1266, 6, 160, 14, 0, 1266, 1267, 6, 160, 15, 0, 1267, 337, 1, 0, 0, 0, 1268, 1269, 5, 105, 0, 0, 1269, 1270, 5, 110, 0, 0, 1270, 1271, 5, 102, 0, 0, 1271, 1272, 5, 111, 0, 0, 1272, 339, 1, 0, 0, 0, 1273, 1274, 3, 58, 21, 0, 1274, 1275, 1, 0, 0, 0, 1275, 1276, 6, 162, 11, 0, 1276, 341, 1, 0, 0, 0, 1277, 1278, 3, 60, 22, 0, 1278, 1279, 1, 0, 0, 0, 1279, 1280, 6, 163, 11, 0, 1280, 343, 1, 0, 0, 0, 1281, 1282, 3, 62, 23, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1284, 6, 164, 11, 0, 1284, 345, 1, 0, 0, 0, 1285, 1286, 3, 78, 31, 0, 1286, 1287, 1, 0, 0, 0, 1287, 1288, 6, 165, 14, 0, 1288, 1289, 6, 165, 15, 0, 1289, 347, 1, 0, 0, 0, 1290, 1291, 5, 102, 0, 0, 1291, 1292, 5, 117, 0, 0, 1292, 1293, 5, 110, 0, 0, 1293, 1294, 5, 99, 0, 0, 1294, 1295, 5, 116, 0, 0, 1295, 1296, 5, 105, 0, 0, 1296, 1297, 5, 111, 0, 0, 1297, 1298, 5, 110, 0, 0, 1298, 1299, 5, 115, 0, 0, 1299, 349, 1, 0, 0, 0, 1300, 1301, 3, 58, 21, 0, 1301, 1302, 1, 0, 0, 0, 1302, 1303, 6, 167, 11, 0, 1303, 351, 1, 0, 0, 0, 1304, 1305, 3, 60, 22, 0, 1305, 1306, 1, 0, 0, 0, 1306, 1307, 6, 168, 11, 0, 1307, 353, 1, 0, 0, 0, 1308, 1309, 3, 62, 23, 0, 1309, 1310, 1, 0, 0, 0, 1310, 1311, 6, 169, 11, 0, 1311, 355, 1, 0, 0, 0, 1312, 1313, 3, 178, 81, 0, 1313, 1314, 1, 0, 0, 0, 1314, 1315, 6, 170, 16, 0, 1315, 1316, 6, 170, 15, 0, 1316, 357, 1, 0, 0, 0, 1317, 1318, 5, 58, 0, 0, 1318, 359, 1, 0, 0, 0, 1319, 1325, 3, 90, 37, 0, 1320, 1325, 3, 80, 32, 0, 1321, 1325, 3, 120, 52, 0, 1322, 1325, 3, 82, 33, 0, 1323, 1325, 3, 96, 40, 0, 1324, 1319, 1, 0, 0, 0, 1324, 1320, 1, 0, 0, 0, 1324, 1321, 1, 0, 0, 0, 1324, 1322, 1, 0, 0, 0, 1324, 1323, 1, 0, 0, 0, 1325, 1326, 1, 0, 0, 0, 1326, 1324, 1, 0, 0, 0, 1326, 1327, 1, 0, 0, 0, 1327, 361, 1, 0, 0, 0, 1328, 1329, 3, 58, 21, 0, 1329, 1330, 1, 0, 0, 0, 1330, 1331, 6, 173, 11, 0, 1331, 363, 1, 0, 0, 0, 1332, 1333, 3, 60, 22, 0, 1333, 1334, 1, 0, 0, 0, 1334, 1335, 6, 174, 11, 0, 1335, 365, 1, 0, 0, 0, 1336, 1337, 3, 62, 23, 0, 1337, 1338, 1, 0, 0, 0, 1338, 1339, 6, 175, 11, 0, 1339, 367, 1, 0, 0, 0, 1340, 1341, 3, 78, 31, 0, 1341, 1342, 1, 0, 0, 0, 1342, 1343, 6, 176, 14, 0, 1343, 1344, 6, 176, 15, 0, 1344, 369, 1, 0, 0, 0, 1345, 1346, 3, 66, 25, 0, 1346, 1347, 1, 0, 0, 0, 1347, 1348, 6, 177, 20, 0, 1348, 1349, 6, 177, 15, 0, 1349, 1350, 6, 177, 31, 0, 1350, 371, 1, 0, 0, 0, 1351, 1352, 3, 58, 21, 0, 1352, 1353, 1, 0, 0, 0, 1353, 1354, 6, 178, 11, 0, 1354, 373, 1, 0, 0, 0, 1355, 1356, 3, 60, 22, 0, 1356, 1357, 1, 0, 0, 0, 1357, 1358, 6, 179, 11, 0, 1358, 375, 1, 0, 0, 0, 1359, 1360, 3, 62, 23, 0, 1360, 1361, 1, 0, 0, 0, 1361, 1362, 6, 180, 11, 0, 1362, 377, 1, 0, 0, 0, 1363, 1364, 3, 116, 50, 0, 1364, 1365, 1, 0, 0, 0, 1365, 1366, 6, 181, 17, 0, 1366, 1367, 6, 181, 15, 0, 1367, 1368, 6, 181, 7, 0, 1368, 379, 1, 0, 0, 0, 1369, 1370, 3, 58, 21, 0, 1370, 1371, 1, 0, 0, 0, 1371, 1372, 6, 182, 11, 0, 1372, 381, 1, 0, 0, 0, 1373, 1374, 3, 60, 22, 0, 1374, 1375, 1, 0, 0, 0, 1375, 1376, 6, 183, 11, 0, 1376, 383, 1, 0, 0, 0, 1377, 1378, 3, 62, 23, 0, 1378, 1379, 1, 0, 0, 0, 1379, 1380, 6, 184, 11, 0, 1380, 385, 1, 0, 0, 0, 1381, 1382, 3, 184, 84, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 6, 185, 15, 0, 1384, 1385, 6, 185, 0, 0, 1385, 1386, 6, 185, 25, 0, 1386, 387, 1, 0, 0, 0, 1387, 1388, 3, 180, 82, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1390, 6, 186, 15, 0, 1390, 1391, 6, 186, 0, 0, 1391, 1392, 6, 186, 30, 0, 1392, 389, 1, 0, 0, 0, 1393, 1394, 3, 106, 45, 0, 1394, 1395, 1, 0, 0, 0, 1395, 1396, 6, 187, 15, 0, 1396, 1397, 6, 187, 0, 0, 1397, 1398, 6, 187, 32, 0, 1398, 391, 1, 0, 0, 0, 1399, 1400, 3, 78, 31, 0, 1400, 1401, 1, 0, 0, 0, 1401, 1402, 6, 188, 14, 0, 1402, 1403, 6, 188, 15, 0, 1403, 393, 1, 0, 0, 0, 62, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 566, 576, 580, 583, 592, 594, 605, 612, 617, 656, 661, 670, 677, 682, 684, 695, 703, 706, 708, 713, 718, 724, 731, 736, 742, 745, 753, 757, 890, 895, 900, 902, 908, 993, 997, 1002, 1007, 1012, 1014, 1018, 1020, 1097, 1101, 1106, 1324, 1326, 33, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 8, 0, 5, 12, 0, 5, 14, 0, 5, 10, 0, 5, 5, 0, 5, 11, 0, 0, 1, 0, 7, 68, 0, 5, 0, 0, 7, 29, 0, 4, 0, 0, 7, 69, 0, 7, 38, 0, 7, 36, 0, 7, 30, 0, 7, 25, 0, 7, 40, 0, 7, 79, 0, 5, 13, 0, 5, 7, 0, 7, 71, 0, 7, 89, 0, 7, 88, 0, 7, 87, 0, 5, 9, 0, 7, 70, 0, 5, 15, 0, 7, 33, 0] \ No newline at end of file +[4, 0, 124, 1422, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 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, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 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, 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, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 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, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 4, 20, 567, 8, 20, 11, 20, 12, 20, 568, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 577, 8, 21, 10, 21, 12, 21, 580, 9, 21, 1, 21, 3, 21, 583, 8, 21, 1, 21, 3, 21, 586, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 595, 8, 22, 10, 22, 12, 22, 598, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 4, 23, 606, 8, 23, 11, 23, 12, 23, 607, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 3, 24, 615, 8, 24, 1, 25, 4, 25, 618, 8, 25, 11, 25, 12, 25, 619, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 659, 8, 36, 1, 36, 4, 36, 662, 8, 36, 11, 36, 12, 36, 663, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 3, 39, 673, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 3, 41, 680, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, 685, 8, 42, 10, 42, 12, 42, 688, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 696, 8, 42, 10, 42, 12, 42, 699, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 706, 8, 42, 1, 42, 3, 42, 709, 8, 42, 3, 42, 711, 8, 42, 1, 43, 4, 43, 714, 8, 43, 11, 43, 12, 43, 715, 1, 44, 4, 44, 719, 8, 44, 11, 44, 12, 44, 720, 1, 44, 1, 44, 5, 44, 725, 8, 44, 10, 44, 12, 44, 728, 9, 44, 1, 44, 1, 44, 4, 44, 732, 8, 44, 11, 44, 12, 44, 733, 1, 44, 4, 44, 737, 8, 44, 11, 44, 12, 44, 738, 1, 44, 1, 44, 5, 44, 743, 8, 44, 10, 44, 12, 44, 746, 9, 44, 3, 44, 748, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 754, 8, 44, 11, 44, 12, 44, 755, 1, 44, 1, 44, 3, 44, 760, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 5, 80, 882, 8, 80, 10, 80, 12, 80, 885, 9, 80, 1, 80, 1, 80, 4, 80, 889, 8, 80, 11, 80, 12, 80, 890, 3, 80, 893, 8, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 5, 83, 907, 8, 83, 10, 83, 12, 83, 910, 9, 83, 1, 83, 1, 83, 3, 83, 914, 8, 83, 1, 83, 4, 83, 917, 8, 83, 11, 83, 12, 83, 918, 3, 83, 921, 8, 83, 1, 84, 1, 84, 4, 84, 925, 8, 84, 11, 84, 12, 84, 926, 1, 84, 1, 84, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 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, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 3, 103, 1012, 8, 103, 1, 104, 1, 104, 3, 104, 1016, 8, 104, 1, 104, 5, 104, 1019, 8, 104, 10, 104, 12, 104, 1022, 9, 104, 1, 104, 1, 104, 3, 104, 1026, 8, 104, 1, 104, 4, 104, 1029, 8, 104, 11, 104, 12, 104, 1030, 3, 104, 1033, 8, 104, 1, 105, 1, 105, 4, 105, 1037, 8, 105, 11, 105, 12, 105, 1038, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 123, 4, 123, 1114, 8, 123, 11, 123, 12, 123, 1115, 1, 123, 1, 123, 3, 123, 1120, 8, 123, 1, 123, 4, 123, 1123, 8, 123, 11, 123, 12, 123, 1124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 4, 173, 1343, 8, 173, 11, 173, 12, 173, 1344, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 2, 596, 697, 0, 190, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 0, 66, 25, 68, 0, 70, 0, 72, 26, 74, 27, 76, 28, 78, 29, 80, 0, 82, 0, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 30, 102, 31, 104, 32, 106, 33, 108, 34, 110, 35, 112, 36, 114, 37, 116, 38, 118, 39, 120, 40, 122, 41, 124, 42, 126, 43, 128, 44, 130, 45, 132, 46, 134, 47, 136, 48, 138, 49, 140, 50, 142, 51, 144, 52, 146, 53, 148, 54, 150, 55, 152, 56, 154, 57, 156, 58, 158, 59, 160, 60, 162, 61, 164, 62, 166, 63, 168, 64, 170, 65, 172, 66, 174, 67, 176, 68, 178, 69, 180, 70, 182, 71, 184, 0, 186, 72, 188, 73, 190, 74, 192, 75, 194, 0, 196, 0, 198, 0, 200, 0, 202, 0, 204, 0, 206, 76, 208, 0, 210, 77, 212, 78, 214, 79, 216, 0, 218, 0, 220, 0, 222, 0, 224, 0, 226, 80, 228, 81, 230, 82, 232, 83, 234, 0, 236, 0, 238, 0, 240, 0, 242, 84, 244, 0, 246, 85, 248, 86, 250, 87, 252, 0, 254, 0, 256, 88, 258, 89, 260, 0, 262, 90, 264, 0, 266, 0, 268, 91, 270, 92, 272, 93, 274, 0, 276, 0, 278, 0, 280, 0, 282, 0, 284, 0, 286, 0, 288, 94, 290, 95, 292, 96, 294, 0, 296, 0, 298, 0, 300, 0, 302, 0, 304, 97, 306, 98, 308, 99, 310, 0, 312, 0, 314, 0, 316, 0, 318, 100, 320, 101, 322, 102, 324, 0, 326, 0, 328, 0, 330, 0, 332, 103, 334, 104, 336, 105, 338, 0, 340, 106, 342, 107, 344, 108, 346, 109, 348, 0, 350, 110, 352, 111, 354, 112, 356, 113, 358, 0, 360, 114, 362, 115, 364, 116, 366, 117, 368, 118, 370, 0, 372, 0, 374, 119, 376, 120, 378, 121, 380, 0, 382, 122, 384, 123, 386, 124, 388, 0, 390, 0, 392, 0, 394, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 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, 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, 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, 1, 0, 96, 96, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1448, 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, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 70, 1, 0, 0, 0, 1, 72, 1, 0, 0, 0, 1, 74, 1, 0, 0, 0, 1, 76, 1, 0, 0, 0, 2, 78, 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, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 170, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 2, 180, 1, 0, 0, 0, 2, 182, 1, 0, 0, 0, 2, 186, 1, 0, 0, 0, 2, 188, 1, 0, 0, 0, 2, 190, 1, 0, 0, 0, 2, 192, 1, 0, 0, 0, 3, 194, 1, 0, 0, 0, 3, 196, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 3, 204, 1, 0, 0, 0, 3, 206, 1, 0, 0, 0, 3, 208, 1, 0, 0, 0, 3, 210, 1, 0, 0, 0, 3, 212, 1, 0, 0, 0, 3, 214, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 220, 1, 0, 0, 0, 4, 226, 1, 0, 0, 0, 4, 228, 1, 0, 0, 0, 4, 230, 1, 0, 0, 0, 4, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 5, 240, 1, 0, 0, 0, 5, 242, 1, 0, 0, 0, 5, 244, 1, 0, 0, 0, 5, 246, 1, 0, 0, 0, 5, 248, 1, 0, 0, 0, 5, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 6, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 7, 282, 1, 0, 0, 0, 7, 284, 1, 0, 0, 0, 7, 286, 1, 0, 0, 0, 7, 288, 1, 0, 0, 0, 7, 290, 1, 0, 0, 0, 7, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 8, 296, 1, 0, 0, 0, 8, 298, 1, 0, 0, 0, 8, 300, 1, 0, 0, 0, 8, 302, 1, 0, 0, 0, 8, 304, 1, 0, 0, 0, 8, 306, 1, 0, 0, 0, 8, 308, 1, 0, 0, 0, 9, 310, 1, 0, 0, 0, 9, 312, 1, 0, 0, 0, 9, 314, 1, 0, 0, 0, 9, 316, 1, 0, 0, 0, 9, 318, 1, 0, 0, 0, 9, 320, 1, 0, 0, 0, 9, 322, 1, 0, 0, 0, 10, 324, 1, 0, 0, 0, 10, 326, 1, 0, 0, 0, 10, 328, 1, 0, 0, 0, 10, 330, 1, 0, 0, 0, 10, 332, 1, 0, 0, 0, 10, 334, 1, 0, 0, 0, 10, 336, 1, 0, 0, 0, 11, 338, 1, 0, 0, 0, 11, 340, 1, 0, 0, 0, 11, 342, 1, 0, 0, 0, 11, 344, 1, 0, 0, 0, 11, 346, 1, 0, 0, 0, 12, 348, 1, 0, 0, 0, 12, 350, 1, 0, 0, 0, 12, 352, 1, 0, 0, 0, 12, 354, 1, 0, 0, 0, 12, 356, 1, 0, 0, 0, 13, 358, 1, 0, 0, 0, 13, 360, 1, 0, 0, 0, 13, 362, 1, 0, 0, 0, 13, 364, 1, 0, 0, 0, 13, 366, 1, 0, 0, 0, 13, 368, 1, 0, 0, 0, 14, 370, 1, 0, 0, 0, 14, 372, 1, 0, 0, 0, 14, 374, 1, 0, 0, 0, 14, 376, 1, 0, 0, 0, 14, 378, 1, 0, 0, 0, 15, 380, 1, 0, 0, 0, 15, 382, 1, 0, 0, 0, 15, 384, 1, 0, 0, 0, 15, 386, 1, 0, 0, 0, 15, 388, 1, 0, 0, 0, 15, 390, 1, 0, 0, 0, 15, 392, 1, 0, 0, 0, 15, 394, 1, 0, 0, 0, 16, 396, 1, 0, 0, 0, 18, 406, 1, 0, 0, 0, 20, 413, 1, 0, 0, 0, 22, 422, 1, 0, 0, 0, 24, 429, 1, 0, 0, 0, 26, 439, 1, 0, 0, 0, 28, 446, 1, 0, 0, 0, 30, 453, 1, 0, 0, 0, 32, 467, 1, 0, 0, 0, 34, 474, 1, 0, 0, 0, 36, 482, 1, 0, 0, 0, 38, 491, 1, 0, 0, 0, 40, 498, 1, 0, 0, 0, 42, 508, 1, 0, 0, 0, 44, 520, 1, 0, 0, 0, 46, 529, 1, 0, 0, 0, 48, 535, 1, 0, 0, 0, 50, 542, 1, 0, 0, 0, 52, 549, 1, 0, 0, 0, 54, 557, 1, 0, 0, 0, 56, 566, 1, 0, 0, 0, 58, 572, 1, 0, 0, 0, 60, 589, 1, 0, 0, 0, 62, 605, 1, 0, 0, 0, 64, 614, 1, 0, 0, 0, 66, 617, 1, 0, 0, 0, 68, 621, 1, 0, 0, 0, 70, 626, 1, 0, 0, 0, 72, 631, 1, 0, 0, 0, 74, 635, 1, 0, 0, 0, 76, 639, 1, 0, 0, 0, 78, 643, 1, 0, 0, 0, 80, 647, 1, 0, 0, 0, 82, 649, 1, 0, 0, 0, 84, 651, 1, 0, 0, 0, 86, 654, 1, 0, 0, 0, 88, 656, 1, 0, 0, 0, 90, 665, 1, 0, 0, 0, 92, 667, 1, 0, 0, 0, 94, 672, 1, 0, 0, 0, 96, 674, 1, 0, 0, 0, 98, 679, 1, 0, 0, 0, 100, 710, 1, 0, 0, 0, 102, 713, 1, 0, 0, 0, 104, 759, 1, 0, 0, 0, 106, 761, 1, 0, 0, 0, 108, 764, 1, 0, 0, 0, 110, 768, 1, 0, 0, 0, 112, 772, 1, 0, 0, 0, 114, 774, 1, 0, 0, 0, 116, 777, 1, 0, 0, 0, 118, 779, 1, 0, 0, 0, 120, 784, 1, 0, 0, 0, 122, 786, 1, 0, 0, 0, 124, 792, 1, 0, 0, 0, 126, 798, 1, 0, 0, 0, 128, 803, 1, 0, 0, 0, 130, 805, 1, 0, 0, 0, 132, 808, 1, 0, 0, 0, 134, 811, 1, 0, 0, 0, 136, 816, 1, 0, 0, 0, 138, 820, 1, 0, 0, 0, 140, 825, 1, 0, 0, 0, 142, 831, 1, 0, 0, 0, 144, 834, 1, 0, 0, 0, 146, 836, 1, 0, 0, 0, 148, 842, 1, 0, 0, 0, 150, 844, 1, 0, 0, 0, 152, 849, 1, 0, 0, 0, 154, 852, 1, 0, 0, 0, 156, 855, 1, 0, 0, 0, 158, 858, 1, 0, 0, 0, 160, 860, 1, 0, 0, 0, 162, 863, 1, 0, 0, 0, 164, 865, 1, 0, 0, 0, 166, 868, 1, 0, 0, 0, 168, 870, 1, 0, 0, 0, 170, 872, 1, 0, 0, 0, 172, 874, 1, 0, 0, 0, 174, 876, 1, 0, 0, 0, 176, 892, 1, 0, 0, 0, 178, 894, 1, 0, 0, 0, 180, 899, 1, 0, 0, 0, 182, 920, 1, 0, 0, 0, 184, 922, 1, 0, 0, 0, 186, 930, 1, 0, 0, 0, 188, 932, 1, 0, 0, 0, 190, 936, 1, 0, 0, 0, 192, 940, 1, 0, 0, 0, 194, 944, 1, 0, 0, 0, 196, 949, 1, 0, 0, 0, 198, 953, 1, 0, 0, 0, 200, 957, 1, 0, 0, 0, 202, 961, 1, 0, 0, 0, 204, 965, 1, 0, 0, 0, 206, 969, 1, 0, 0, 0, 208, 978, 1, 0, 0, 0, 210, 982, 1, 0, 0, 0, 212, 986, 1, 0, 0, 0, 214, 990, 1, 0, 0, 0, 216, 994, 1, 0, 0, 0, 218, 999, 1, 0, 0, 0, 220, 1003, 1, 0, 0, 0, 222, 1011, 1, 0, 0, 0, 224, 1032, 1, 0, 0, 0, 226, 1036, 1, 0, 0, 0, 228, 1040, 1, 0, 0, 0, 230, 1044, 1, 0, 0, 0, 232, 1048, 1, 0, 0, 0, 234, 1052, 1, 0, 0, 0, 236, 1057, 1, 0, 0, 0, 238, 1061, 1, 0, 0, 0, 240, 1065, 1, 0, 0, 0, 242, 1069, 1, 0, 0, 0, 244, 1072, 1, 0, 0, 0, 246, 1076, 1, 0, 0, 0, 248, 1080, 1, 0, 0, 0, 250, 1084, 1, 0, 0, 0, 252, 1088, 1, 0, 0, 0, 254, 1093, 1, 0, 0, 0, 256, 1098, 1, 0, 0, 0, 258, 1103, 1, 0, 0, 0, 260, 1110, 1, 0, 0, 0, 262, 1119, 1, 0, 0, 0, 264, 1126, 1, 0, 0, 0, 266, 1130, 1, 0, 0, 0, 268, 1134, 1, 0, 0, 0, 270, 1138, 1, 0, 0, 0, 272, 1142, 1, 0, 0, 0, 274, 1146, 1, 0, 0, 0, 276, 1152, 1, 0, 0, 0, 278, 1156, 1, 0, 0, 0, 280, 1160, 1, 0, 0, 0, 282, 1164, 1, 0, 0, 0, 284, 1168, 1, 0, 0, 0, 286, 1172, 1, 0, 0, 0, 288, 1176, 1, 0, 0, 0, 290, 1180, 1, 0, 0, 0, 292, 1184, 1, 0, 0, 0, 294, 1188, 1, 0, 0, 0, 296, 1193, 1, 0, 0, 0, 298, 1197, 1, 0, 0, 0, 300, 1201, 1, 0, 0, 0, 302, 1206, 1, 0, 0, 0, 304, 1210, 1, 0, 0, 0, 306, 1214, 1, 0, 0, 0, 308, 1218, 1, 0, 0, 0, 310, 1222, 1, 0, 0, 0, 312, 1228, 1, 0, 0, 0, 314, 1232, 1, 0, 0, 0, 316, 1236, 1, 0, 0, 0, 318, 1240, 1, 0, 0, 0, 320, 1244, 1, 0, 0, 0, 322, 1248, 1, 0, 0, 0, 324, 1252, 1, 0, 0, 0, 326, 1257, 1, 0, 0, 0, 328, 1261, 1, 0, 0, 0, 330, 1265, 1, 0, 0, 0, 332, 1269, 1, 0, 0, 0, 334, 1273, 1, 0, 0, 0, 336, 1277, 1, 0, 0, 0, 338, 1281, 1, 0, 0, 0, 340, 1286, 1, 0, 0, 0, 342, 1291, 1, 0, 0, 0, 344, 1295, 1, 0, 0, 0, 346, 1299, 1, 0, 0, 0, 348, 1303, 1, 0, 0, 0, 350, 1308, 1, 0, 0, 0, 352, 1318, 1, 0, 0, 0, 354, 1322, 1, 0, 0, 0, 356, 1326, 1, 0, 0, 0, 358, 1330, 1, 0, 0, 0, 360, 1335, 1, 0, 0, 0, 362, 1342, 1, 0, 0, 0, 364, 1346, 1, 0, 0, 0, 366, 1350, 1, 0, 0, 0, 368, 1354, 1, 0, 0, 0, 370, 1358, 1, 0, 0, 0, 372, 1363, 1, 0, 0, 0, 374, 1369, 1, 0, 0, 0, 376, 1373, 1, 0, 0, 0, 378, 1377, 1, 0, 0, 0, 380, 1381, 1, 0, 0, 0, 382, 1387, 1, 0, 0, 0, 384, 1391, 1, 0, 0, 0, 386, 1395, 1, 0, 0, 0, 388, 1399, 1, 0, 0, 0, 390, 1405, 1, 0, 0, 0, 392, 1411, 1, 0, 0, 0, 394, 1417, 1, 0, 0, 0, 396, 397, 5, 100, 0, 0, 397, 398, 5, 105, 0, 0, 398, 399, 5, 115, 0, 0, 399, 400, 5, 115, 0, 0, 400, 401, 5, 101, 0, 0, 401, 402, 5, 99, 0, 0, 402, 403, 5, 116, 0, 0, 403, 404, 1, 0, 0, 0, 404, 405, 6, 0, 0, 0, 405, 17, 1, 0, 0, 0, 406, 407, 5, 100, 0, 0, 407, 408, 5, 114, 0, 0, 408, 409, 5, 111, 0, 0, 409, 410, 5, 112, 0, 0, 410, 411, 1, 0, 0, 0, 411, 412, 6, 1, 1, 0, 412, 19, 1, 0, 0, 0, 413, 414, 5, 101, 0, 0, 414, 415, 5, 110, 0, 0, 415, 416, 5, 114, 0, 0, 416, 417, 5, 105, 0, 0, 417, 418, 5, 99, 0, 0, 418, 419, 5, 104, 0, 0, 419, 420, 1, 0, 0, 0, 420, 421, 6, 2, 2, 0, 421, 21, 1, 0, 0, 0, 422, 423, 5, 101, 0, 0, 423, 424, 5, 118, 0, 0, 424, 425, 5, 97, 0, 0, 425, 426, 5, 108, 0, 0, 426, 427, 1, 0, 0, 0, 427, 428, 6, 3, 0, 0, 428, 23, 1, 0, 0, 0, 429, 430, 5, 101, 0, 0, 430, 431, 5, 120, 0, 0, 431, 432, 5, 112, 0, 0, 432, 433, 5, 108, 0, 0, 433, 434, 5, 97, 0, 0, 434, 435, 5, 105, 0, 0, 435, 436, 5, 110, 0, 0, 436, 437, 1, 0, 0, 0, 437, 438, 6, 4, 3, 0, 438, 25, 1, 0, 0, 0, 439, 440, 5, 102, 0, 0, 440, 441, 5, 114, 0, 0, 441, 442, 5, 111, 0, 0, 442, 443, 5, 109, 0, 0, 443, 444, 1, 0, 0, 0, 444, 445, 6, 5, 4, 0, 445, 27, 1, 0, 0, 0, 446, 447, 5, 103, 0, 0, 447, 448, 5, 114, 0, 0, 448, 449, 5, 111, 0, 0, 449, 450, 5, 107, 0, 0, 450, 451, 1, 0, 0, 0, 451, 452, 6, 6, 0, 0, 452, 29, 1, 0, 0, 0, 453, 454, 5, 105, 0, 0, 454, 455, 5, 110, 0, 0, 455, 456, 5, 108, 0, 0, 456, 457, 5, 105, 0, 0, 457, 458, 5, 110, 0, 0, 458, 459, 5, 101, 0, 0, 459, 460, 5, 115, 0, 0, 460, 461, 5, 116, 0, 0, 461, 462, 5, 97, 0, 0, 462, 463, 5, 116, 0, 0, 463, 464, 5, 115, 0, 0, 464, 465, 1, 0, 0, 0, 465, 466, 6, 7, 0, 0, 466, 31, 1, 0, 0, 0, 467, 468, 5, 107, 0, 0, 468, 469, 5, 101, 0, 0, 469, 470, 5, 101, 0, 0, 470, 471, 5, 112, 0, 0, 471, 472, 1, 0, 0, 0, 472, 473, 6, 8, 1, 0, 473, 33, 1, 0, 0, 0, 474, 475, 5, 108, 0, 0, 475, 476, 5, 105, 0, 0, 476, 477, 5, 109, 0, 0, 477, 478, 5, 105, 0, 0, 478, 479, 5, 116, 0, 0, 479, 480, 1, 0, 0, 0, 480, 481, 6, 9, 0, 0, 481, 35, 1, 0, 0, 0, 482, 483, 5, 108, 0, 0, 483, 484, 5, 111, 0, 0, 484, 485, 5, 111, 0, 0, 485, 486, 5, 107, 0, 0, 486, 487, 5, 117, 0, 0, 487, 488, 5, 112, 0, 0, 488, 489, 1, 0, 0, 0, 489, 490, 6, 10, 5, 0, 490, 37, 1, 0, 0, 0, 491, 492, 5, 109, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 116, 0, 0, 494, 495, 5, 97, 0, 0, 495, 496, 1, 0, 0, 0, 496, 497, 6, 11, 6, 0, 497, 39, 1, 0, 0, 0, 498, 499, 5, 109, 0, 0, 499, 500, 5, 101, 0, 0, 500, 501, 5, 116, 0, 0, 501, 502, 5, 114, 0, 0, 502, 503, 5, 105, 0, 0, 503, 504, 5, 99, 0, 0, 504, 505, 5, 115, 0, 0, 505, 506, 1, 0, 0, 0, 506, 507, 6, 12, 7, 0, 507, 41, 1, 0, 0, 0, 508, 509, 5, 109, 0, 0, 509, 510, 5, 118, 0, 0, 510, 511, 5, 95, 0, 0, 511, 512, 5, 101, 0, 0, 512, 513, 5, 120, 0, 0, 513, 514, 5, 112, 0, 0, 514, 515, 5, 97, 0, 0, 515, 516, 5, 110, 0, 0, 516, 517, 5, 100, 0, 0, 517, 518, 1, 0, 0, 0, 518, 519, 6, 13, 8, 0, 519, 43, 1, 0, 0, 0, 520, 521, 5, 114, 0, 0, 521, 522, 5, 101, 0, 0, 522, 523, 5, 110, 0, 0, 523, 524, 5, 97, 0, 0, 524, 525, 5, 109, 0, 0, 525, 526, 5, 101, 0, 0, 526, 527, 1, 0, 0, 0, 527, 528, 6, 14, 9, 0, 528, 45, 1, 0, 0, 0, 529, 530, 5, 114, 0, 0, 530, 531, 5, 111, 0, 0, 531, 532, 5, 119, 0, 0, 532, 533, 1, 0, 0, 0, 533, 534, 6, 15, 0, 0, 534, 47, 1, 0, 0, 0, 535, 536, 5, 115, 0, 0, 536, 537, 5, 104, 0, 0, 537, 538, 5, 111, 0, 0, 538, 539, 5, 119, 0, 0, 539, 540, 1, 0, 0, 0, 540, 541, 6, 16, 10, 0, 541, 49, 1, 0, 0, 0, 542, 543, 5, 115, 0, 0, 543, 544, 5, 111, 0, 0, 544, 545, 5, 114, 0, 0, 545, 546, 5, 116, 0, 0, 546, 547, 1, 0, 0, 0, 547, 548, 6, 17, 0, 0, 548, 51, 1, 0, 0, 0, 549, 550, 5, 115, 0, 0, 550, 551, 5, 116, 0, 0, 551, 552, 5, 97, 0, 0, 552, 553, 5, 116, 0, 0, 553, 554, 5, 115, 0, 0, 554, 555, 1, 0, 0, 0, 555, 556, 6, 18, 0, 0, 556, 53, 1, 0, 0, 0, 557, 558, 5, 119, 0, 0, 558, 559, 5, 104, 0, 0, 559, 560, 5, 101, 0, 0, 560, 561, 5, 114, 0, 0, 561, 562, 5, 101, 0, 0, 562, 563, 1, 0, 0, 0, 563, 564, 6, 19, 0, 0, 564, 55, 1, 0, 0, 0, 565, 567, 8, 0, 0, 0, 566, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 566, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 571, 6, 20, 0, 0, 571, 57, 1, 0, 0, 0, 572, 573, 5, 47, 0, 0, 573, 574, 5, 47, 0, 0, 574, 578, 1, 0, 0, 0, 575, 577, 8, 1, 0, 0, 576, 575, 1, 0, 0, 0, 577, 580, 1, 0, 0, 0, 578, 576, 1, 0, 0, 0, 578, 579, 1, 0, 0, 0, 579, 582, 1, 0, 0, 0, 580, 578, 1, 0, 0, 0, 581, 583, 5, 13, 0, 0, 582, 581, 1, 0, 0, 0, 582, 583, 1, 0, 0, 0, 583, 585, 1, 0, 0, 0, 584, 586, 5, 10, 0, 0, 585, 584, 1, 0, 0, 0, 585, 586, 1, 0, 0, 0, 586, 587, 1, 0, 0, 0, 587, 588, 6, 21, 11, 0, 588, 59, 1, 0, 0, 0, 589, 590, 5, 47, 0, 0, 590, 591, 5, 42, 0, 0, 591, 596, 1, 0, 0, 0, 592, 595, 3, 60, 22, 0, 593, 595, 9, 0, 0, 0, 594, 592, 1, 0, 0, 0, 594, 593, 1, 0, 0, 0, 595, 598, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 596, 594, 1, 0, 0, 0, 597, 599, 1, 0, 0, 0, 598, 596, 1, 0, 0, 0, 599, 600, 5, 42, 0, 0, 600, 601, 5, 47, 0, 0, 601, 602, 1, 0, 0, 0, 602, 603, 6, 22, 11, 0, 603, 61, 1, 0, 0, 0, 604, 606, 7, 2, 0, 0, 605, 604, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 605, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 1, 0, 0, 0, 609, 610, 6, 23, 11, 0, 610, 63, 1, 0, 0, 0, 611, 615, 8, 3, 0, 0, 612, 613, 5, 47, 0, 0, 613, 615, 8, 4, 0, 0, 614, 611, 1, 0, 0, 0, 614, 612, 1, 0, 0, 0, 615, 65, 1, 0, 0, 0, 616, 618, 3, 64, 24, 0, 617, 616, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 617, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 67, 1, 0, 0, 0, 621, 622, 3, 178, 81, 0, 622, 623, 1, 0, 0, 0, 623, 624, 6, 26, 12, 0, 624, 625, 6, 26, 13, 0, 625, 69, 1, 0, 0, 0, 626, 627, 3, 78, 31, 0, 627, 628, 1, 0, 0, 0, 628, 629, 6, 27, 14, 0, 629, 630, 6, 27, 15, 0, 630, 71, 1, 0, 0, 0, 631, 632, 3, 62, 23, 0, 632, 633, 1, 0, 0, 0, 633, 634, 6, 28, 11, 0, 634, 73, 1, 0, 0, 0, 635, 636, 3, 58, 21, 0, 636, 637, 1, 0, 0, 0, 637, 638, 6, 29, 11, 0, 638, 75, 1, 0, 0, 0, 639, 640, 3, 60, 22, 0, 640, 641, 1, 0, 0, 0, 641, 642, 6, 30, 11, 0, 642, 77, 1, 0, 0, 0, 643, 644, 5, 124, 0, 0, 644, 645, 1, 0, 0, 0, 645, 646, 6, 31, 15, 0, 646, 79, 1, 0, 0, 0, 647, 648, 7, 5, 0, 0, 648, 81, 1, 0, 0, 0, 649, 650, 7, 6, 0, 0, 650, 83, 1, 0, 0, 0, 651, 652, 5, 92, 0, 0, 652, 653, 7, 7, 0, 0, 653, 85, 1, 0, 0, 0, 654, 655, 8, 8, 0, 0, 655, 87, 1, 0, 0, 0, 656, 658, 7, 9, 0, 0, 657, 659, 7, 10, 0, 0, 658, 657, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 661, 1, 0, 0, 0, 660, 662, 3, 80, 32, 0, 661, 660, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 89, 1, 0, 0, 0, 665, 666, 5, 64, 0, 0, 666, 91, 1, 0, 0, 0, 667, 668, 5, 96, 0, 0, 668, 93, 1, 0, 0, 0, 669, 673, 8, 11, 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, 95, 1, 0, 0, 0, 674, 675, 5, 95, 0, 0, 675, 97, 1, 0, 0, 0, 676, 680, 3, 82, 33, 0, 677, 680, 3, 80, 32, 0, 678, 680, 3, 96, 40, 0, 679, 676, 1, 0, 0, 0, 679, 677, 1, 0, 0, 0, 679, 678, 1, 0, 0, 0, 680, 99, 1, 0, 0, 0, 681, 686, 5, 34, 0, 0, 682, 685, 3, 84, 34, 0, 683, 685, 3, 86, 35, 0, 684, 682, 1, 0, 0, 0, 684, 683, 1, 0, 0, 0, 685, 688, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 686, 687, 1, 0, 0, 0, 687, 689, 1, 0, 0, 0, 688, 686, 1, 0, 0, 0, 689, 711, 5, 34, 0, 0, 690, 691, 5, 34, 0, 0, 691, 692, 5, 34, 0, 0, 692, 693, 5, 34, 0, 0, 693, 697, 1, 0, 0, 0, 694, 696, 8, 1, 0, 0, 695, 694, 1, 0, 0, 0, 696, 699, 1, 0, 0, 0, 697, 698, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 698, 700, 1, 0, 0, 0, 699, 697, 1, 0, 0, 0, 700, 701, 5, 34, 0, 0, 701, 702, 5, 34, 0, 0, 702, 703, 5, 34, 0, 0, 703, 705, 1, 0, 0, 0, 704, 706, 5, 34, 0, 0, 705, 704, 1, 0, 0, 0, 705, 706, 1, 0, 0, 0, 706, 708, 1, 0, 0, 0, 707, 709, 5, 34, 0, 0, 708, 707, 1, 0, 0, 0, 708, 709, 1, 0, 0, 0, 709, 711, 1, 0, 0, 0, 710, 681, 1, 0, 0, 0, 710, 690, 1, 0, 0, 0, 711, 101, 1, 0, 0, 0, 712, 714, 3, 80, 32, 0, 713, 712, 1, 0, 0, 0, 714, 715, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 103, 1, 0, 0, 0, 717, 719, 3, 80, 32, 0, 718, 717, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 718, 1, 0, 0, 0, 720, 721, 1, 0, 0, 0, 721, 722, 1, 0, 0, 0, 722, 726, 3, 120, 52, 0, 723, 725, 3, 80, 32, 0, 724, 723, 1, 0, 0, 0, 725, 728, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 760, 1, 0, 0, 0, 728, 726, 1, 0, 0, 0, 729, 731, 3, 120, 52, 0, 730, 732, 3, 80, 32, 0, 731, 730, 1, 0, 0, 0, 732, 733, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 733, 734, 1, 0, 0, 0, 734, 760, 1, 0, 0, 0, 735, 737, 3, 80, 32, 0, 736, 735, 1, 0, 0, 0, 737, 738, 1, 0, 0, 0, 738, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 747, 1, 0, 0, 0, 740, 744, 3, 120, 52, 0, 741, 743, 3, 80, 32, 0, 742, 741, 1, 0, 0, 0, 743, 746, 1, 0, 0, 0, 744, 742, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 748, 1, 0, 0, 0, 746, 744, 1, 0, 0, 0, 747, 740, 1, 0, 0, 0, 747, 748, 1, 0, 0, 0, 748, 749, 1, 0, 0, 0, 749, 750, 3, 88, 36, 0, 750, 760, 1, 0, 0, 0, 751, 753, 3, 120, 52, 0, 752, 754, 3, 80, 32, 0, 753, 752, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 753, 1, 0, 0, 0, 755, 756, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 758, 3, 88, 36, 0, 758, 760, 1, 0, 0, 0, 759, 718, 1, 0, 0, 0, 759, 729, 1, 0, 0, 0, 759, 736, 1, 0, 0, 0, 759, 751, 1, 0, 0, 0, 760, 105, 1, 0, 0, 0, 761, 762, 5, 98, 0, 0, 762, 763, 5, 121, 0, 0, 763, 107, 1, 0, 0, 0, 764, 765, 5, 97, 0, 0, 765, 766, 5, 110, 0, 0, 766, 767, 5, 100, 0, 0, 767, 109, 1, 0, 0, 0, 768, 769, 5, 97, 0, 0, 769, 770, 5, 115, 0, 0, 770, 771, 5, 99, 0, 0, 771, 111, 1, 0, 0, 0, 772, 773, 5, 61, 0, 0, 773, 113, 1, 0, 0, 0, 774, 775, 5, 58, 0, 0, 775, 776, 5, 58, 0, 0, 776, 115, 1, 0, 0, 0, 777, 778, 5, 44, 0, 0, 778, 117, 1, 0, 0, 0, 779, 780, 5, 100, 0, 0, 780, 781, 5, 101, 0, 0, 781, 782, 5, 115, 0, 0, 782, 783, 5, 99, 0, 0, 783, 119, 1, 0, 0, 0, 784, 785, 5, 46, 0, 0, 785, 121, 1, 0, 0, 0, 786, 787, 5, 102, 0, 0, 787, 788, 5, 97, 0, 0, 788, 789, 5, 108, 0, 0, 789, 790, 5, 115, 0, 0, 790, 791, 5, 101, 0, 0, 791, 123, 1, 0, 0, 0, 792, 793, 5, 102, 0, 0, 793, 794, 5, 105, 0, 0, 794, 795, 5, 114, 0, 0, 795, 796, 5, 115, 0, 0, 796, 797, 5, 116, 0, 0, 797, 125, 1, 0, 0, 0, 798, 799, 5, 108, 0, 0, 799, 800, 5, 97, 0, 0, 800, 801, 5, 115, 0, 0, 801, 802, 5, 116, 0, 0, 802, 127, 1, 0, 0, 0, 803, 804, 5, 40, 0, 0, 804, 129, 1, 0, 0, 0, 805, 806, 5, 105, 0, 0, 806, 807, 5, 110, 0, 0, 807, 131, 1, 0, 0, 0, 808, 809, 5, 105, 0, 0, 809, 810, 5, 115, 0, 0, 810, 133, 1, 0, 0, 0, 811, 812, 5, 108, 0, 0, 812, 813, 5, 105, 0, 0, 813, 814, 5, 107, 0, 0, 814, 815, 5, 101, 0, 0, 815, 135, 1, 0, 0, 0, 816, 817, 5, 110, 0, 0, 817, 818, 5, 111, 0, 0, 818, 819, 5, 116, 0, 0, 819, 137, 1, 0, 0, 0, 820, 821, 5, 110, 0, 0, 821, 822, 5, 117, 0, 0, 822, 823, 5, 108, 0, 0, 823, 824, 5, 108, 0, 0, 824, 139, 1, 0, 0, 0, 825, 826, 5, 110, 0, 0, 826, 827, 5, 117, 0, 0, 827, 828, 5, 108, 0, 0, 828, 829, 5, 108, 0, 0, 829, 830, 5, 115, 0, 0, 830, 141, 1, 0, 0, 0, 831, 832, 5, 111, 0, 0, 832, 833, 5, 114, 0, 0, 833, 143, 1, 0, 0, 0, 834, 835, 5, 63, 0, 0, 835, 145, 1, 0, 0, 0, 836, 837, 5, 114, 0, 0, 837, 838, 5, 108, 0, 0, 838, 839, 5, 105, 0, 0, 839, 840, 5, 107, 0, 0, 840, 841, 5, 101, 0, 0, 841, 147, 1, 0, 0, 0, 842, 843, 5, 41, 0, 0, 843, 149, 1, 0, 0, 0, 844, 845, 5, 116, 0, 0, 845, 846, 5, 114, 0, 0, 846, 847, 5, 117, 0, 0, 847, 848, 5, 101, 0, 0, 848, 151, 1, 0, 0, 0, 849, 850, 5, 61, 0, 0, 850, 851, 5, 61, 0, 0, 851, 153, 1, 0, 0, 0, 852, 853, 5, 61, 0, 0, 853, 854, 5, 126, 0, 0, 854, 155, 1, 0, 0, 0, 855, 856, 5, 33, 0, 0, 856, 857, 5, 61, 0, 0, 857, 157, 1, 0, 0, 0, 858, 859, 5, 60, 0, 0, 859, 159, 1, 0, 0, 0, 860, 861, 5, 60, 0, 0, 861, 862, 5, 61, 0, 0, 862, 161, 1, 0, 0, 0, 863, 864, 5, 62, 0, 0, 864, 163, 1, 0, 0, 0, 865, 866, 5, 62, 0, 0, 866, 867, 5, 61, 0, 0, 867, 165, 1, 0, 0, 0, 868, 869, 5, 43, 0, 0, 869, 167, 1, 0, 0, 0, 870, 871, 5, 45, 0, 0, 871, 169, 1, 0, 0, 0, 872, 873, 5, 42, 0, 0, 873, 171, 1, 0, 0, 0, 874, 875, 5, 47, 0, 0, 875, 173, 1, 0, 0, 0, 876, 877, 5, 37, 0, 0, 877, 175, 1, 0, 0, 0, 878, 879, 3, 144, 64, 0, 879, 883, 3, 82, 33, 0, 880, 882, 3, 98, 41, 0, 881, 880, 1, 0, 0, 0, 882, 885, 1, 0, 0, 0, 883, 881, 1, 0, 0, 0, 883, 884, 1, 0, 0, 0, 884, 893, 1, 0, 0, 0, 885, 883, 1, 0, 0, 0, 886, 888, 3, 144, 64, 0, 887, 889, 3, 80, 32, 0, 888, 887, 1, 0, 0, 0, 889, 890, 1, 0, 0, 0, 890, 888, 1, 0, 0, 0, 890, 891, 1, 0, 0, 0, 891, 893, 1, 0, 0, 0, 892, 878, 1, 0, 0, 0, 892, 886, 1, 0, 0, 0, 893, 177, 1, 0, 0, 0, 894, 895, 5, 91, 0, 0, 895, 896, 1, 0, 0, 0, 896, 897, 6, 81, 0, 0, 897, 898, 6, 81, 0, 0, 898, 179, 1, 0, 0, 0, 899, 900, 5, 93, 0, 0, 900, 901, 1, 0, 0, 0, 901, 902, 6, 82, 15, 0, 902, 903, 6, 82, 15, 0, 903, 181, 1, 0, 0, 0, 904, 908, 3, 82, 33, 0, 905, 907, 3, 98, 41, 0, 906, 905, 1, 0, 0, 0, 907, 910, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 921, 1, 0, 0, 0, 910, 908, 1, 0, 0, 0, 911, 914, 3, 96, 40, 0, 912, 914, 3, 90, 37, 0, 913, 911, 1, 0, 0, 0, 913, 912, 1, 0, 0, 0, 914, 916, 1, 0, 0, 0, 915, 917, 3, 98, 41, 0, 916, 915, 1, 0, 0, 0, 917, 918, 1, 0, 0, 0, 918, 916, 1, 0, 0, 0, 918, 919, 1, 0, 0, 0, 919, 921, 1, 0, 0, 0, 920, 904, 1, 0, 0, 0, 920, 913, 1, 0, 0, 0, 921, 183, 1, 0, 0, 0, 922, 924, 3, 92, 38, 0, 923, 925, 3, 94, 39, 0, 924, 923, 1, 0, 0, 0, 925, 926, 1, 0, 0, 0, 926, 924, 1, 0, 0, 0, 926, 927, 1, 0, 0, 0, 927, 928, 1, 0, 0, 0, 928, 929, 3, 92, 38, 0, 929, 185, 1, 0, 0, 0, 930, 931, 3, 184, 84, 0, 931, 187, 1, 0, 0, 0, 932, 933, 3, 58, 21, 0, 933, 934, 1, 0, 0, 0, 934, 935, 6, 86, 11, 0, 935, 189, 1, 0, 0, 0, 936, 937, 3, 60, 22, 0, 937, 938, 1, 0, 0, 0, 938, 939, 6, 87, 11, 0, 939, 191, 1, 0, 0, 0, 940, 941, 3, 62, 23, 0, 941, 942, 1, 0, 0, 0, 942, 943, 6, 88, 11, 0, 943, 193, 1, 0, 0, 0, 944, 945, 3, 78, 31, 0, 945, 946, 1, 0, 0, 0, 946, 947, 6, 89, 14, 0, 947, 948, 6, 89, 15, 0, 948, 195, 1, 0, 0, 0, 949, 950, 3, 178, 81, 0, 950, 951, 1, 0, 0, 0, 951, 952, 6, 90, 12, 0, 952, 197, 1, 0, 0, 0, 953, 954, 3, 180, 82, 0, 954, 955, 1, 0, 0, 0, 955, 956, 6, 91, 16, 0, 956, 199, 1, 0, 0, 0, 957, 958, 3, 116, 50, 0, 958, 959, 1, 0, 0, 0, 959, 960, 6, 92, 17, 0, 960, 201, 1, 0, 0, 0, 961, 962, 3, 112, 48, 0, 962, 963, 1, 0, 0, 0, 963, 964, 6, 93, 18, 0, 964, 203, 1, 0, 0, 0, 965, 966, 3, 100, 42, 0, 966, 967, 1, 0, 0, 0, 967, 968, 6, 94, 19, 0, 968, 205, 1, 0, 0, 0, 969, 970, 5, 109, 0, 0, 970, 971, 5, 101, 0, 0, 971, 972, 5, 116, 0, 0, 972, 973, 5, 97, 0, 0, 973, 974, 5, 100, 0, 0, 974, 975, 5, 97, 0, 0, 975, 976, 5, 116, 0, 0, 976, 977, 5, 97, 0, 0, 977, 207, 1, 0, 0, 0, 978, 979, 3, 66, 25, 0, 979, 980, 1, 0, 0, 0, 980, 981, 6, 96, 20, 0, 981, 209, 1, 0, 0, 0, 982, 983, 3, 58, 21, 0, 983, 984, 1, 0, 0, 0, 984, 985, 6, 97, 11, 0, 985, 211, 1, 0, 0, 0, 986, 987, 3, 60, 22, 0, 987, 988, 1, 0, 0, 0, 988, 989, 6, 98, 11, 0, 989, 213, 1, 0, 0, 0, 990, 991, 3, 62, 23, 0, 991, 992, 1, 0, 0, 0, 992, 993, 6, 99, 11, 0, 993, 215, 1, 0, 0, 0, 994, 995, 3, 78, 31, 0, 995, 996, 1, 0, 0, 0, 996, 997, 6, 100, 14, 0, 997, 998, 6, 100, 15, 0, 998, 217, 1, 0, 0, 0, 999, 1000, 3, 120, 52, 0, 1000, 1001, 1, 0, 0, 0, 1001, 1002, 6, 101, 21, 0, 1002, 219, 1, 0, 0, 0, 1003, 1004, 3, 116, 50, 0, 1004, 1005, 1, 0, 0, 0, 1005, 1006, 6, 102, 17, 0, 1006, 221, 1, 0, 0, 0, 1007, 1012, 3, 82, 33, 0, 1008, 1012, 3, 80, 32, 0, 1009, 1012, 3, 96, 40, 0, 1010, 1012, 3, 170, 77, 0, 1011, 1007, 1, 0, 0, 0, 1011, 1008, 1, 0, 0, 0, 1011, 1009, 1, 0, 0, 0, 1011, 1010, 1, 0, 0, 0, 1012, 223, 1, 0, 0, 0, 1013, 1016, 3, 82, 33, 0, 1014, 1016, 3, 170, 77, 0, 1015, 1013, 1, 0, 0, 0, 1015, 1014, 1, 0, 0, 0, 1016, 1020, 1, 0, 0, 0, 1017, 1019, 3, 222, 103, 0, 1018, 1017, 1, 0, 0, 0, 1019, 1022, 1, 0, 0, 0, 1020, 1018, 1, 0, 0, 0, 1020, 1021, 1, 0, 0, 0, 1021, 1033, 1, 0, 0, 0, 1022, 1020, 1, 0, 0, 0, 1023, 1026, 3, 96, 40, 0, 1024, 1026, 3, 90, 37, 0, 1025, 1023, 1, 0, 0, 0, 1025, 1024, 1, 0, 0, 0, 1026, 1028, 1, 0, 0, 0, 1027, 1029, 3, 222, 103, 0, 1028, 1027, 1, 0, 0, 0, 1029, 1030, 1, 0, 0, 0, 1030, 1028, 1, 0, 0, 0, 1030, 1031, 1, 0, 0, 0, 1031, 1033, 1, 0, 0, 0, 1032, 1015, 1, 0, 0, 0, 1032, 1025, 1, 0, 0, 0, 1033, 225, 1, 0, 0, 0, 1034, 1037, 3, 224, 104, 0, 1035, 1037, 3, 184, 84, 0, 1036, 1034, 1, 0, 0, 0, 1036, 1035, 1, 0, 0, 0, 1037, 1038, 1, 0, 0, 0, 1038, 1036, 1, 0, 0, 0, 1038, 1039, 1, 0, 0, 0, 1039, 227, 1, 0, 0, 0, 1040, 1041, 3, 58, 21, 0, 1041, 1042, 1, 0, 0, 0, 1042, 1043, 6, 106, 11, 0, 1043, 229, 1, 0, 0, 0, 1044, 1045, 3, 60, 22, 0, 1045, 1046, 1, 0, 0, 0, 1046, 1047, 6, 107, 11, 0, 1047, 231, 1, 0, 0, 0, 1048, 1049, 3, 62, 23, 0, 1049, 1050, 1, 0, 0, 0, 1050, 1051, 6, 108, 11, 0, 1051, 233, 1, 0, 0, 0, 1052, 1053, 3, 78, 31, 0, 1053, 1054, 1, 0, 0, 0, 1054, 1055, 6, 109, 14, 0, 1055, 1056, 6, 109, 15, 0, 1056, 235, 1, 0, 0, 0, 1057, 1058, 3, 112, 48, 0, 1058, 1059, 1, 0, 0, 0, 1059, 1060, 6, 110, 18, 0, 1060, 237, 1, 0, 0, 0, 1061, 1062, 3, 116, 50, 0, 1062, 1063, 1, 0, 0, 0, 1063, 1064, 6, 111, 17, 0, 1064, 239, 1, 0, 0, 0, 1065, 1066, 3, 120, 52, 0, 1066, 1067, 1, 0, 0, 0, 1067, 1068, 6, 112, 21, 0, 1068, 241, 1, 0, 0, 0, 1069, 1070, 5, 97, 0, 0, 1070, 1071, 5, 115, 0, 0, 1071, 243, 1, 0, 0, 0, 1072, 1073, 3, 226, 105, 0, 1073, 1074, 1, 0, 0, 0, 1074, 1075, 6, 114, 22, 0, 1075, 245, 1, 0, 0, 0, 1076, 1077, 3, 58, 21, 0, 1077, 1078, 1, 0, 0, 0, 1078, 1079, 6, 115, 11, 0, 1079, 247, 1, 0, 0, 0, 1080, 1081, 3, 60, 22, 0, 1081, 1082, 1, 0, 0, 0, 1082, 1083, 6, 116, 11, 0, 1083, 249, 1, 0, 0, 0, 1084, 1085, 3, 62, 23, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1087, 6, 117, 11, 0, 1087, 251, 1, 0, 0, 0, 1088, 1089, 3, 78, 31, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1091, 6, 118, 14, 0, 1091, 1092, 6, 118, 15, 0, 1092, 253, 1, 0, 0, 0, 1093, 1094, 3, 178, 81, 0, 1094, 1095, 1, 0, 0, 0, 1095, 1096, 6, 119, 12, 0, 1096, 1097, 6, 119, 23, 0, 1097, 255, 1, 0, 0, 0, 1098, 1099, 5, 111, 0, 0, 1099, 1100, 5, 110, 0, 0, 1100, 1101, 1, 0, 0, 0, 1101, 1102, 6, 120, 24, 0, 1102, 257, 1, 0, 0, 0, 1103, 1104, 5, 119, 0, 0, 1104, 1105, 5, 105, 0, 0, 1105, 1106, 5, 116, 0, 0, 1106, 1107, 5, 104, 0, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1109, 6, 121, 24, 0, 1109, 259, 1, 0, 0, 0, 1110, 1111, 8, 12, 0, 0, 1111, 261, 1, 0, 0, 0, 1112, 1114, 3, 260, 122, 0, 1113, 1112, 1, 0, 0, 0, 1114, 1115, 1, 0, 0, 0, 1115, 1113, 1, 0, 0, 0, 1115, 1116, 1, 0, 0, 0, 1116, 1117, 1, 0, 0, 0, 1117, 1118, 3, 360, 172, 0, 1118, 1120, 1, 0, 0, 0, 1119, 1113, 1, 0, 0, 0, 1119, 1120, 1, 0, 0, 0, 1120, 1122, 1, 0, 0, 0, 1121, 1123, 3, 260, 122, 0, 1122, 1121, 1, 0, 0, 0, 1123, 1124, 1, 0, 0, 0, 1124, 1122, 1, 0, 0, 0, 1124, 1125, 1, 0, 0, 0, 1125, 263, 1, 0, 0, 0, 1126, 1127, 3, 186, 85, 0, 1127, 1128, 1, 0, 0, 0, 1128, 1129, 6, 124, 25, 0, 1129, 265, 1, 0, 0, 0, 1130, 1131, 3, 262, 123, 0, 1131, 1132, 1, 0, 0, 0, 1132, 1133, 6, 125, 26, 0, 1133, 267, 1, 0, 0, 0, 1134, 1135, 3, 58, 21, 0, 1135, 1136, 1, 0, 0, 0, 1136, 1137, 6, 126, 11, 0, 1137, 269, 1, 0, 0, 0, 1138, 1139, 3, 60, 22, 0, 1139, 1140, 1, 0, 0, 0, 1140, 1141, 6, 127, 11, 0, 1141, 271, 1, 0, 0, 0, 1142, 1143, 3, 62, 23, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1145, 6, 128, 11, 0, 1145, 273, 1, 0, 0, 0, 1146, 1147, 3, 78, 31, 0, 1147, 1148, 1, 0, 0, 0, 1148, 1149, 6, 129, 14, 0, 1149, 1150, 6, 129, 15, 0, 1150, 1151, 6, 129, 15, 0, 1151, 275, 1, 0, 0, 0, 1152, 1153, 3, 112, 48, 0, 1153, 1154, 1, 0, 0, 0, 1154, 1155, 6, 130, 18, 0, 1155, 277, 1, 0, 0, 0, 1156, 1157, 3, 116, 50, 0, 1157, 1158, 1, 0, 0, 0, 1158, 1159, 6, 131, 17, 0, 1159, 279, 1, 0, 0, 0, 1160, 1161, 3, 120, 52, 0, 1161, 1162, 1, 0, 0, 0, 1162, 1163, 6, 132, 21, 0, 1163, 281, 1, 0, 0, 0, 1164, 1165, 3, 258, 121, 0, 1165, 1166, 1, 0, 0, 0, 1166, 1167, 6, 133, 27, 0, 1167, 283, 1, 0, 0, 0, 1168, 1169, 3, 226, 105, 0, 1169, 1170, 1, 0, 0, 0, 1170, 1171, 6, 134, 22, 0, 1171, 285, 1, 0, 0, 0, 1172, 1173, 3, 186, 85, 0, 1173, 1174, 1, 0, 0, 0, 1174, 1175, 6, 135, 25, 0, 1175, 287, 1, 0, 0, 0, 1176, 1177, 3, 58, 21, 0, 1177, 1178, 1, 0, 0, 0, 1178, 1179, 6, 136, 11, 0, 1179, 289, 1, 0, 0, 0, 1180, 1181, 3, 60, 22, 0, 1181, 1182, 1, 0, 0, 0, 1182, 1183, 6, 137, 11, 0, 1183, 291, 1, 0, 0, 0, 1184, 1185, 3, 62, 23, 0, 1185, 1186, 1, 0, 0, 0, 1186, 1187, 6, 138, 11, 0, 1187, 293, 1, 0, 0, 0, 1188, 1189, 3, 78, 31, 0, 1189, 1190, 1, 0, 0, 0, 1190, 1191, 6, 139, 14, 0, 1191, 1192, 6, 139, 15, 0, 1192, 295, 1, 0, 0, 0, 1193, 1194, 3, 116, 50, 0, 1194, 1195, 1, 0, 0, 0, 1195, 1196, 6, 140, 17, 0, 1196, 297, 1, 0, 0, 0, 1197, 1198, 3, 120, 52, 0, 1198, 1199, 1, 0, 0, 0, 1199, 1200, 6, 141, 21, 0, 1200, 299, 1, 0, 0, 0, 1201, 1202, 3, 256, 120, 0, 1202, 1203, 1, 0, 0, 0, 1203, 1204, 6, 142, 28, 0, 1204, 1205, 6, 142, 29, 0, 1205, 301, 1, 0, 0, 0, 1206, 1207, 3, 66, 25, 0, 1207, 1208, 1, 0, 0, 0, 1208, 1209, 6, 143, 20, 0, 1209, 303, 1, 0, 0, 0, 1210, 1211, 3, 58, 21, 0, 1211, 1212, 1, 0, 0, 0, 1212, 1213, 6, 144, 11, 0, 1213, 305, 1, 0, 0, 0, 1214, 1215, 3, 60, 22, 0, 1215, 1216, 1, 0, 0, 0, 1216, 1217, 6, 145, 11, 0, 1217, 307, 1, 0, 0, 0, 1218, 1219, 3, 62, 23, 0, 1219, 1220, 1, 0, 0, 0, 1220, 1221, 6, 146, 11, 0, 1221, 309, 1, 0, 0, 0, 1222, 1223, 3, 78, 31, 0, 1223, 1224, 1, 0, 0, 0, 1224, 1225, 6, 147, 14, 0, 1225, 1226, 6, 147, 15, 0, 1226, 1227, 6, 147, 15, 0, 1227, 311, 1, 0, 0, 0, 1228, 1229, 3, 116, 50, 0, 1229, 1230, 1, 0, 0, 0, 1230, 1231, 6, 148, 17, 0, 1231, 313, 1, 0, 0, 0, 1232, 1233, 3, 120, 52, 0, 1233, 1234, 1, 0, 0, 0, 1234, 1235, 6, 149, 21, 0, 1235, 315, 1, 0, 0, 0, 1236, 1237, 3, 226, 105, 0, 1237, 1238, 1, 0, 0, 0, 1238, 1239, 6, 150, 22, 0, 1239, 317, 1, 0, 0, 0, 1240, 1241, 3, 58, 21, 0, 1241, 1242, 1, 0, 0, 0, 1242, 1243, 6, 151, 11, 0, 1243, 319, 1, 0, 0, 0, 1244, 1245, 3, 60, 22, 0, 1245, 1246, 1, 0, 0, 0, 1246, 1247, 6, 152, 11, 0, 1247, 321, 1, 0, 0, 0, 1248, 1249, 3, 62, 23, 0, 1249, 1250, 1, 0, 0, 0, 1250, 1251, 6, 153, 11, 0, 1251, 323, 1, 0, 0, 0, 1252, 1253, 3, 78, 31, 0, 1253, 1254, 1, 0, 0, 0, 1254, 1255, 6, 154, 14, 0, 1255, 1256, 6, 154, 15, 0, 1256, 325, 1, 0, 0, 0, 1257, 1258, 3, 120, 52, 0, 1258, 1259, 1, 0, 0, 0, 1259, 1260, 6, 155, 21, 0, 1260, 327, 1, 0, 0, 0, 1261, 1262, 3, 186, 85, 0, 1262, 1263, 1, 0, 0, 0, 1263, 1264, 6, 156, 25, 0, 1264, 329, 1, 0, 0, 0, 1265, 1266, 3, 182, 83, 0, 1266, 1267, 1, 0, 0, 0, 1267, 1268, 6, 157, 30, 0, 1268, 331, 1, 0, 0, 0, 1269, 1270, 3, 58, 21, 0, 1270, 1271, 1, 0, 0, 0, 1271, 1272, 6, 158, 11, 0, 1272, 333, 1, 0, 0, 0, 1273, 1274, 3, 60, 22, 0, 1274, 1275, 1, 0, 0, 0, 1275, 1276, 6, 159, 11, 0, 1276, 335, 1, 0, 0, 0, 1277, 1278, 3, 62, 23, 0, 1278, 1279, 1, 0, 0, 0, 1279, 1280, 6, 160, 11, 0, 1280, 337, 1, 0, 0, 0, 1281, 1282, 3, 78, 31, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1284, 6, 161, 14, 0, 1284, 1285, 6, 161, 15, 0, 1285, 339, 1, 0, 0, 0, 1286, 1287, 5, 105, 0, 0, 1287, 1288, 5, 110, 0, 0, 1288, 1289, 5, 102, 0, 0, 1289, 1290, 5, 111, 0, 0, 1290, 341, 1, 0, 0, 0, 1291, 1292, 3, 58, 21, 0, 1292, 1293, 1, 0, 0, 0, 1293, 1294, 6, 163, 11, 0, 1294, 343, 1, 0, 0, 0, 1295, 1296, 3, 60, 22, 0, 1296, 1297, 1, 0, 0, 0, 1297, 1298, 6, 164, 11, 0, 1298, 345, 1, 0, 0, 0, 1299, 1300, 3, 62, 23, 0, 1300, 1301, 1, 0, 0, 0, 1301, 1302, 6, 165, 11, 0, 1302, 347, 1, 0, 0, 0, 1303, 1304, 3, 78, 31, 0, 1304, 1305, 1, 0, 0, 0, 1305, 1306, 6, 166, 14, 0, 1306, 1307, 6, 166, 15, 0, 1307, 349, 1, 0, 0, 0, 1308, 1309, 5, 102, 0, 0, 1309, 1310, 5, 117, 0, 0, 1310, 1311, 5, 110, 0, 0, 1311, 1312, 5, 99, 0, 0, 1312, 1313, 5, 116, 0, 0, 1313, 1314, 5, 105, 0, 0, 1314, 1315, 5, 111, 0, 0, 1315, 1316, 5, 110, 0, 0, 1316, 1317, 5, 115, 0, 0, 1317, 351, 1, 0, 0, 0, 1318, 1319, 3, 58, 21, 0, 1319, 1320, 1, 0, 0, 0, 1320, 1321, 6, 168, 11, 0, 1321, 353, 1, 0, 0, 0, 1322, 1323, 3, 60, 22, 0, 1323, 1324, 1, 0, 0, 0, 1324, 1325, 6, 169, 11, 0, 1325, 355, 1, 0, 0, 0, 1326, 1327, 3, 62, 23, 0, 1327, 1328, 1, 0, 0, 0, 1328, 1329, 6, 170, 11, 0, 1329, 357, 1, 0, 0, 0, 1330, 1331, 3, 180, 82, 0, 1331, 1332, 1, 0, 0, 0, 1332, 1333, 6, 171, 16, 0, 1333, 1334, 6, 171, 15, 0, 1334, 359, 1, 0, 0, 0, 1335, 1336, 5, 58, 0, 0, 1336, 361, 1, 0, 0, 0, 1337, 1343, 3, 90, 37, 0, 1338, 1343, 3, 80, 32, 0, 1339, 1343, 3, 120, 52, 0, 1340, 1343, 3, 82, 33, 0, 1341, 1343, 3, 96, 40, 0, 1342, 1337, 1, 0, 0, 0, 1342, 1338, 1, 0, 0, 0, 1342, 1339, 1, 0, 0, 0, 1342, 1340, 1, 0, 0, 0, 1342, 1341, 1, 0, 0, 0, 1343, 1344, 1, 0, 0, 0, 1344, 1342, 1, 0, 0, 0, 1344, 1345, 1, 0, 0, 0, 1345, 363, 1, 0, 0, 0, 1346, 1347, 3, 58, 21, 0, 1347, 1348, 1, 0, 0, 0, 1348, 1349, 6, 174, 11, 0, 1349, 365, 1, 0, 0, 0, 1350, 1351, 3, 60, 22, 0, 1351, 1352, 1, 0, 0, 0, 1352, 1353, 6, 175, 11, 0, 1353, 367, 1, 0, 0, 0, 1354, 1355, 3, 62, 23, 0, 1355, 1356, 1, 0, 0, 0, 1356, 1357, 6, 176, 11, 0, 1357, 369, 1, 0, 0, 0, 1358, 1359, 3, 78, 31, 0, 1359, 1360, 1, 0, 0, 0, 1360, 1361, 6, 177, 14, 0, 1361, 1362, 6, 177, 15, 0, 1362, 371, 1, 0, 0, 0, 1363, 1364, 3, 66, 25, 0, 1364, 1365, 1, 0, 0, 0, 1365, 1366, 6, 178, 20, 0, 1366, 1367, 6, 178, 15, 0, 1367, 1368, 6, 178, 31, 0, 1368, 373, 1, 0, 0, 0, 1369, 1370, 3, 58, 21, 0, 1370, 1371, 1, 0, 0, 0, 1371, 1372, 6, 179, 11, 0, 1372, 375, 1, 0, 0, 0, 1373, 1374, 3, 60, 22, 0, 1374, 1375, 1, 0, 0, 0, 1375, 1376, 6, 180, 11, 0, 1376, 377, 1, 0, 0, 0, 1377, 1378, 3, 62, 23, 0, 1378, 1379, 1, 0, 0, 0, 1379, 1380, 6, 181, 11, 0, 1380, 379, 1, 0, 0, 0, 1381, 1382, 3, 116, 50, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 6, 182, 17, 0, 1384, 1385, 6, 182, 15, 0, 1385, 1386, 6, 182, 7, 0, 1386, 381, 1, 0, 0, 0, 1387, 1388, 3, 58, 21, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1390, 6, 183, 11, 0, 1390, 383, 1, 0, 0, 0, 1391, 1392, 3, 60, 22, 0, 1392, 1393, 1, 0, 0, 0, 1393, 1394, 6, 184, 11, 0, 1394, 385, 1, 0, 0, 0, 1395, 1396, 3, 62, 23, 0, 1396, 1397, 1, 0, 0, 0, 1397, 1398, 6, 185, 11, 0, 1398, 387, 1, 0, 0, 0, 1399, 1400, 3, 186, 85, 0, 1400, 1401, 1, 0, 0, 0, 1401, 1402, 6, 186, 15, 0, 1402, 1403, 6, 186, 0, 0, 1403, 1404, 6, 186, 25, 0, 1404, 389, 1, 0, 0, 0, 1405, 1406, 3, 182, 83, 0, 1406, 1407, 1, 0, 0, 0, 1407, 1408, 6, 187, 15, 0, 1408, 1409, 6, 187, 0, 0, 1409, 1410, 6, 187, 30, 0, 1410, 391, 1, 0, 0, 0, 1411, 1412, 3, 106, 45, 0, 1412, 1413, 1, 0, 0, 0, 1413, 1414, 6, 188, 15, 0, 1414, 1415, 6, 188, 0, 0, 1415, 1416, 6, 188, 32, 0, 1416, 393, 1, 0, 0, 0, 1417, 1418, 3, 78, 31, 0, 1418, 1419, 1, 0, 0, 0, 1419, 1420, 6, 189, 14, 0, 1420, 1421, 6, 189, 15, 0, 1421, 395, 1, 0, 0, 0, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 568, 578, 582, 585, 594, 596, 607, 614, 619, 658, 663, 672, 679, 684, 686, 697, 705, 708, 710, 715, 720, 726, 733, 738, 744, 747, 755, 759, 883, 890, 892, 908, 913, 918, 920, 926, 1011, 1015, 1020, 1025, 1030, 1032, 1036, 1038, 1115, 1119, 1124, 1342, 1344, 33, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 8, 0, 5, 12, 0, 5, 14, 0, 5, 10, 0, 5, 5, 0, 5, 11, 0, 0, 1, 0, 7, 69, 0, 5, 0, 0, 7, 29, 0, 4, 0, 0, 7, 70, 0, 7, 38, 0, 7, 36, 0, 7, 30, 0, 7, 25, 0, 7, 40, 0, 7, 80, 0, 5, 13, 0, 5, 7, 0, 7, 72, 0, 7, 90, 0, 7, 89, 0, 7, 88, 0, 5, 9, 0, 7, 71, 0, 5, 15, 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 f9ca7ff95c847..1511be73d40e1 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 @@ -26,22 +26,23 @@ public class EsqlBaseLexer extends Lexer { CAST_OP=37, COMMA=38, DESC=39, DOT=40, FALSE=41, FIRST=42, LAST=43, LP=44, IN=45, IS=46, LIKE=47, NOT=48, NULL=49, NULLS=50, OR=51, PARAM=52, RLIKE=53, RP=54, TRUE=55, EQ=56, CIEQ=57, NEQ=58, LT=59, LTE=60, GT=61, GTE=62, - PLUS=63, MINUS=64, ASTERISK=65, SLASH=66, PERCENT=67, OPENING_BRACKET=68, - CLOSING_BRACKET=69, UNQUOTED_IDENTIFIER=70, QUOTED_IDENTIFIER=71, EXPR_LINE_COMMENT=72, - EXPR_MULTILINE_COMMENT=73, EXPR_WS=74, METADATA=75, FROM_LINE_COMMENT=76, - FROM_MULTILINE_COMMENT=77, FROM_WS=78, ID_PATTERN=79, PROJECT_LINE_COMMENT=80, - PROJECT_MULTILINE_COMMENT=81, PROJECT_WS=82, AS=83, RENAME_LINE_COMMENT=84, - RENAME_MULTILINE_COMMENT=85, RENAME_WS=86, ON=87, WITH=88, ENRICH_POLICY_NAME=89, - ENRICH_LINE_COMMENT=90, ENRICH_MULTILINE_COMMENT=91, ENRICH_WS=92, ENRICH_FIELD_LINE_COMMENT=93, - ENRICH_FIELD_MULTILINE_COMMENT=94, ENRICH_FIELD_WS=95, LOOKUP_LINE_COMMENT=96, - LOOKUP_MULTILINE_COMMENT=97, LOOKUP_WS=98, LOOKUP_FIELD_LINE_COMMENT=99, - LOOKUP_FIELD_MULTILINE_COMMENT=100, LOOKUP_FIELD_WS=101, MVEXPAND_LINE_COMMENT=102, - MVEXPAND_MULTILINE_COMMENT=103, MVEXPAND_WS=104, INFO=105, SHOW_LINE_COMMENT=106, - SHOW_MULTILINE_COMMENT=107, SHOW_WS=108, FUNCTIONS=109, META_LINE_COMMENT=110, - META_MULTILINE_COMMENT=111, META_WS=112, COLON=113, SETTING=114, SETTING_LINE_COMMENT=115, - SETTTING_MULTILINE_COMMENT=116, SETTING_WS=117, METRICS_LINE_COMMENT=118, - METRICS_MULTILINE_COMMENT=119, METRICS_WS=120, CLOSING_METRICS_LINE_COMMENT=121, - CLOSING_METRICS_MULTILINE_COMMENT=122, CLOSING_METRICS_WS=123; + PLUS=63, MINUS=64, ASTERISK=65, SLASH=66, PERCENT=67, NAMED_OR_POSITIONAL_PARAM=68, + OPENING_BRACKET=69, CLOSING_BRACKET=70, UNQUOTED_IDENTIFIER=71, QUOTED_IDENTIFIER=72, + EXPR_LINE_COMMENT=73, EXPR_MULTILINE_COMMENT=74, EXPR_WS=75, METADATA=76, + FROM_LINE_COMMENT=77, FROM_MULTILINE_COMMENT=78, FROM_WS=79, ID_PATTERN=80, + PROJECT_LINE_COMMENT=81, PROJECT_MULTILINE_COMMENT=82, PROJECT_WS=83, + AS=84, RENAME_LINE_COMMENT=85, RENAME_MULTILINE_COMMENT=86, RENAME_WS=87, + ON=88, WITH=89, ENRICH_POLICY_NAME=90, ENRICH_LINE_COMMENT=91, ENRICH_MULTILINE_COMMENT=92, + ENRICH_WS=93, ENRICH_FIELD_LINE_COMMENT=94, ENRICH_FIELD_MULTILINE_COMMENT=95, + ENRICH_FIELD_WS=96, LOOKUP_LINE_COMMENT=97, LOOKUP_MULTILINE_COMMENT=98, + LOOKUP_WS=99, LOOKUP_FIELD_LINE_COMMENT=100, LOOKUP_FIELD_MULTILINE_COMMENT=101, + LOOKUP_FIELD_WS=102, MVEXPAND_LINE_COMMENT=103, MVEXPAND_MULTILINE_COMMENT=104, + MVEXPAND_WS=105, INFO=106, SHOW_LINE_COMMENT=107, SHOW_MULTILINE_COMMENT=108, + SHOW_WS=109, FUNCTIONS=110, META_LINE_COMMENT=111, META_MULTILINE_COMMENT=112, + META_WS=113, COLON=114, SETTING=115, SETTING_LINE_COMMENT=116, SETTTING_MULTILINE_COMMENT=117, + SETTING_WS=118, METRICS_LINE_COMMENT=119, METRICS_MULTILINE_COMMENT=120, + METRICS_WS=121, CLOSING_METRICS_LINE_COMMENT=122, CLOSING_METRICS_MULTILINE_COMMENT=123, + CLOSING_METRICS_WS=124; public static final int EXPLAIN_MODE=1, EXPRESSION_MODE=2, FROM_MODE=3, PROJECT_MODE=4, RENAME_MODE=5, ENRICH_MODE=6, ENRICH_FIELD_MODE=7, LOOKUP_MODE=8, LOOKUP_FIELD_MODE=9, @@ -72,28 +73,29 @@ private static String[] makeRuleNames() { "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", - "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", - "QUOTED_ID", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", - "EXPR_WS", "FROM_PIPE", "FROM_OPENING_BRACKET", "FROM_CLOSING_BRACKET", - "FROM_COMMA", "FROM_ASSIGN", "FROM_QUOTED_STRING", "METADATA", "FROM_INDEX_UNQUOTED_IDENTIFIER", - "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", "PROJECT_PIPE", - "PROJECT_DOT", "PROJECT_COMMA", "UNQUOTED_ID_BODY_WITH_PATTERN", "UNQUOTED_ID_PATTERN", - "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", - "RENAME_PIPE", "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", "AS", "RENAME_ID_PATTERN", - "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "ENRICH_PIPE", - "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", "ENRICH_POLICY_NAME", - "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", "ENRICH_LINE_COMMENT", - "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", "ENRICH_FIELD_ASSIGN", - "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", "ENRICH_FIELD_ID_PATTERN", - "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", - "ENRICH_FIELD_WS", "LOOKUP_PIPE", "LOOKUP_COMMA", "LOOKUP_DOT", "LOOKUP_ON", - "LOOKUP_INDEX_UNQUOTED_IDENTIFIER", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", - "LOOKUP_WS", "LOOKUP_FIELD_PIPE", "LOOKUP_FIELD_COMMA", "LOOKUP_FIELD_DOT", - "LOOKUP_FIELD_ID_PATTERN", "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", - "LOOKUP_FIELD_WS", "MVEXPAND_PIPE", "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", - "MVEXPAND_UNQUOTED_IDENTIFIER", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", - "MVEXPAND_WS", "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", - "SHOW_WS", "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", + "PERCENT", "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_ID", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", + "EXPR_MULTILINE_COMMENT", "EXPR_WS", "FROM_PIPE", "FROM_OPENING_BRACKET", + "FROM_CLOSING_BRACKET", "FROM_COMMA", "FROM_ASSIGN", "FROM_QUOTED_STRING", + "METADATA", "FROM_INDEX_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", + "FROM_WS", "PROJECT_PIPE", "PROJECT_DOT", "PROJECT_COMMA", "UNQUOTED_ID_BODY_WITH_PATTERN", + "UNQUOTED_ID_PATTERN", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", + "PROJECT_WS", "RENAME_PIPE", "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", + "AS", "RENAME_ID_PATTERN", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", + "RENAME_WS", "ENRICH_PIPE", "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", + "ENRICH_POLICY_NAME", "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", + "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", + "ENRICH_FIELD_ASSIGN", "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", + "ENRICH_FIELD_ID_PATTERN", "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", + "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "LOOKUP_PIPE", "LOOKUP_COMMA", + "LOOKUP_DOT", "LOOKUP_ON", "LOOKUP_INDEX_UNQUOTED_IDENTIFIER", "LOOKUP_LINE_COMMENT", + "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", "LOOKUP_FIELD_PIPE", "LOOKUP_FIELD_COMMA", + "LOOKUP_FIELD_DOT", "LOOKUP_FIELD_ID_PATTERN", "LOOKUP_FIELD_LINE_COMMENT", + "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", "MVEXPAND_PIPE", + "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", "MVEXPAND_UNQUOTED_IDENTIFIER", + "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", + "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", "SHOW_WS", + "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", "META_WS", "SETTING_CLOSING_BRACKET", "COLON", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "METRICS_PIPE", "METRICS_INDEX_UNQUOTED_IDENTIFIER", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", "CLOSING_METRICS_COMMA", @@ -114,11 +116,11 @@ private static String[] makeLiteralNames() { "'desc'", "'.'", "'false'", "'first'", "'last'", "'('", "'in'", "'is'", "'like'", "'not'", "'null'", "'nulls'", "'or'", "'?'", "'rlike'", "')'", "'true'", "'=='", "'=~'", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", - "'-'", "'*'", "'/'", "'%'", null, "']'", null, null, null, null, null, - "'metadata'", null, null, null, null, null, null, null, "'as'", null, - null, null, "'on'", "'with'", null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, "'info'", null, - null, null, "'functions'", null, null, null, "':'" + "'-'", "'*'", "'/'", "'%'", null, null, "']'", null, null, null, null, + null, "'metadata'", null, null, null, null, null, null, null, "'as'", + null, null, null, "'on'", "'with'", null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "'info'", + null, null, null, "'functions'", null, null, null, "':'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); @@ -133,21 +135,21 @@ private static String[] makeSymbolicNames() { "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "EQ", "CIEQ", "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", - "METADATA", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", - "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", - "AS", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", - "ON", "WITH", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", - "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", - "ENRICH_FIELD_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", - "LOOKUP_WS", "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", - "LOOKUP_FIELD_WS", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", - "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", - "SHOW_WS", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", - "META_WS", "COLON", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", - "SETTING_WS", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", - "CLOSING_METRICS_LINE_COMMENT", "CLOSING_METRICS_MULTILINE_COMMENT", + "PERCENT", "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "METADATA", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", + "FROM_WS", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", + "PROJECT_WS", "AS", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", + "RENAME_WS", "ON", "WITH", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", + "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", + "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "LOOKUP_LINE_COMMENT", + "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", "LOOKUP_FIELD_LINE_COMMENT", + "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", "MVEXPAND_LINE_COMMENT", + "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", + "SHOW_MULTILINE_COMMENT", "SHOW_WS", "FUNCTIONS", "META_LINE_COMMENT", + "META_MULTILINE_COMMENT", "META_WS", "COLON", "SETTING", "SETTING_LINE_COMMENT", + "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", + "METRICS_WS", "CLOSING_METRICS_LINE_COMMENT", "CLOSING_METRICS_MULTILINE_COMMENT", "CLOSING_METRICS_WS" }; } @@ -211,7 +213,7 @@ public EsqlBaseLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\u0004\u0000{\u057c\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ + "\u0004\u0000|\u058e\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ "\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ "\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ "\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ @@ -265,58 +267,58 @@ public EsqlBaseLexer(CharStream input) { "\u0002\u00b4\u0007\u00b4\u0002\u00b5\u0007\u00b5\u0002\u00b6\u0007\u00b6"+ "\u0002\u00b7\u0007\u00b7\u0002\u00b8\u0007\u00b8\u0002\u00b9\u0007\u00b9"+ "\u0002\u00ba\u0007\u00ba\u0002\u00bb\u0007\u00bb\u0002\u00bc\u0007\u00bc"+ + "\u0002\u00bd\u0007\u00bd\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+ "\u0001\u0000\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\u0004\u0001\u0004"+ + "\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\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\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\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\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\f\u0001\r\u0001"+ - "\r\u0001\r\u0001\r\u0001\r\u0001\r\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\u000e\u0001\u000e\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\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012"+ - "\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+ - "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0004\u0014"+ - "\u0235\b\u0014\u000b\u0014\f\u0014\u0236\u0001\u0014\u0001\u0014\u0001"+ - "\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0005\u0015\u023f\b\u0015\n"+ - "\u0015\f\u0015\u0242\t\u0015\u0001\u0015\u0003\u0015\u0245\b\u0015\u0001"+ - "\u0015\u0003\u0015\u0248\b\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001"+ - "\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0005\u0016\u0251\b\u0016\n"+ - "\u0016\f\u0016\u0254\t\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+ - "\u0016\u0001\u0016\u0001\u0017\u0004\u0017\u025c\b\u0017\u000b\u0017\f"+ - "\u0017\u025d\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018"+ - "\u0003\u0018\u0265\b\u0018\u0001\u0019\u0004\u0019\u0268\b\u0019\u000b"+ - "\u0019\f\u0019\u0269\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ - "\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001"+ - "\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001"+ - "\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0001"+ - "\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001!\u0001"+ - "!\u0001\"\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0003$\u0291\b$"+ - "\u0001$\u0004$\u0294\b$\u000b$\f$\u0295\u0001%\u0001%\u0001&\u0001&\u0001"+ - "\'\u0001\'\u0001\'\u0003\'\u029f\b\'\u0001(\u0001(\u0001)\u0001)\u0001"+ - ")\u0003)\u02a6\b)\u0001*\u0001*\u0001*\u0005*\u02ab\b*\n*\f*\u02ae\t*"+ - "\u0001*\u0001*\u0001*\u0001*\u0001*\u0001*\u0005*\u02b6\b*\n*\f*\u02b9"+ - "\t*\u0001*\u0001*\u0001*\u0001*\u0001*\u0003*\u02c0\b*\u0001*\u0003*\u02c3"+ - "\b*\u0003*\u02c5\b*\u0001+\u0004+\u02c8\b+\u000b+\f+\u02c9\u0001,\u0004"+ - ",\u02cd\b,\u000b,\f,\u02ce\u0001,\u0001,\u0005,\u02d3\b,\n,\f,\u02d6\t"+ - ",\u0001,\u0001,\u0004,\u02da\b,\u000b,\f,\u02db\u0001,\u0004,\u02df\b"+ - ",\u000b,\f,\u02e0\u0001,\u0001,\u0005,\u02e5\b,\n,\f,\u02e8\t,\u0003,"+ - "\u02ea\b,\u0001,\u0001,\u0001,\u0001,\u0004,\u02f0\b,\u000b,\f,\u02f1"+ - "\u0001,\u0001,\u0003,\u02f6\b,\u0001-\u0001-\u0001-\u0001.\u0001.\u0001"+ + "\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\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\f\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\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\u000e\u0001\u000e"+ + "\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\u0012\u0001\u0012\u0001\u0012\u0001\u0012"+ + "\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013"+ + "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+ + "\u0001\u0014\u0004\u0014\u0237\b\u0014\u000b\u0014\f\u0014\u0238\u0001"+ + "\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0005"+ + "\u0015\u0241\b\u0015\n\u0015\f\u0015\u0244\t\u0015\u0001\u0015\u0003\u0015"+ + "\u0247\b\u0015\u0001\u0015\u0003\u0015\u024a\b\u0015\u0001\u0015\u0001"+ + "\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0005"+ + "\u0016\u0253\b\u0016\n\u0016\f\u0016\u0256\t\u0016\u0001\u0016\u0001\u0016"+ + "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0004\u0017\u025e\b\u0017"+ + "\u000b\u0017\f\u0017\u025f\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+ + "\u0001\u0018\u0003\u0018\u0267\b\u0018\u0001\u0019\u0004\u0019\u026a\b"+ + "\u0019\u000b\u0019\f\u0019\u026b\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ + "\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001"+ + "\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001"+ + "\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001"+ + "\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001"+ + "!\u0001!\u0001\"\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0003$\u0293"+ + "\b$\u0001$\u0004$\u0296\b$\u000b$\f$\u0297\u0001%\u0001%\u0001&\u0001"+ + "&\u0001\'\u0001\'\u0001\'\u0003\'\u02a1\b\'\u0001(\u0001(\u0001)\u0001"+ + ")\u0001)\u0003)\u02a8\b)\u0001*\u0001*\u0001*\u0005*\u02ad\b*\n*\f*\u02b0"+ + "\t*\u0001*\u0001*\u0001*\u0001*\u0001*\u0001*\u0005*\u02b8\b*\n*\f*\u02bb"+ + "\t*\u0001*\u0001*\u0001*\u0001*\u0001*\u0003*\u02c2\b*\u0001*\u0003*\u02c5"+ + "\b*\u0003*\u02c7\b*\u0001+\u0004+\u02ca\b+\u000b+\f+\u02cb\u0001,\u0004"+ + ",\u02cf\b,\u000b,\f,\u02d0\u0001,\u0001,\u0005,\u02d5\b,\n,\f,\u02d8\t"+ + ",\u0001,\u0001,\u0004,\u02dc\b,\u000b,\f,\u02dd\u0001,\u0004,\u02e1\b"+ + ",\u000b,\f,\u02e2\u0001,\u0001,\u0005,\u02e7\b,\n,\f,\u02ea\t,\u0003,"+ + "\u02ec\b,\u0001,\u0001,\u0001,\u0001,\u0004,\u02f2\b,\u000b,\f,\u02f3"+ + "\u0001,\u0001,\u0003,\u02f8\b,\u0001-\u0001-\u0001-\u0001.\u0001.\u0001"+ ".\u0001.\u0001/\u0001/\u0001/\u0001/\u00010\u00010\u00011\u00011\u0001"+ "1\u00012\u00012\u00013\u00013\u00013\u00013\u00013\u00014\u00014\u0001"+ "5\u00015\u00015\u00015\u00015\u00015\u00016\u00016\u00016\u00016\u0001"+ @@ -328,782 +330,794 @@ public EsqlBaseLexer(CharStream input) { "C\u0001C\u0001C\u0001D\u0001D\u0001D\u0001E\u0001E\u0001E\u0001F\u0001"+ "F\u0001F\u0001G\u0001G\u0001H\u0001H\u0001H\u0001I\u0001I\u0001J\u0001"+ "J\u0001J\u0001K\u0001K\u0001L\u0001L\u0001M\u0001M\u0001N\u0001N\u0001"+ - "O\u0001O\u0001P\u0001P\u0001P\u0001P\u0001P\u0001Q\u0001Q\u0001Q\u0001"+ - "Q\u0001Q\u0001R\u0001R\u0005R\u0379\bR\nR\fR\u037c\tR\u0001R\u0001R\u0003"+ - "R\u0380\bR\u0001R\u0004R\u0383\bR\u000bR\fR\u0384\u0003R\u0387\bR\u0001"+ - "S\u0001S\u0004S\u038b\bS\u000bS\fS\u038c\u0001S\u0001S\u0001T\u0001T\u0001"+ - "U\u0001U\u0001U\u0001U\u0001V\u0001V\u0001V\u0001V\u0001W\u0001W\u0001"+ - "W\u0001W\u0001X\u0001X\u0001X\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0001"+ - "Y\u0001Z\u0001Z\u0001Z\u0001Z\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`\u0001a\u0001a\u0001a\u0001a\u0001b\u0001b\u0001"+ - "b\u0001b\u0001c\u0001c\u0001c\u0001c\u0001c\u0001d\u0001d\u0001d\u0001"+ - "d\u0001e\u0001e\u0001e\u0001e\u0001f\u0001f\u0001f\u0001f\u0003f\u03e2"+ - "\bf\u0001g\u0001g\u0003g\u03e6\bg\u0001g\u0005g\u03e9\bg\ng\fg\u03ec\t"+ - "g\u0001g\u0001g\u0003g\u03f0\bg\u0001g\u0004g\u03f3\bg\u000bg\fg\u03f4"+ - "\u0003g\u03f7\bg\u0001h\u0001h\u0004h\u03fb\bh\u000bh\fh\u03fc\u0001i"+ - "\u0001i\u0001i\u0001i\u0001j\u0001j\u0001j\u0001j\u0001k\u0001k\u0001"+ - "k\u0001k\u0001l\u0001l\u0001l\u0001l\u0001l\u0001m\u0001m\u0001m\u0001"+ - "m\u0001n\u0001n\u0001n\u0001n\u0001o\u0001o\u0001o\u0001o\u0001p\u0001"+ - "p\u0001p\u0001q\u0001q\u0001q\u0001q\u0001r\u0001r\u0001r\u0001r\u0001"+ - "s\u0001s\u0001s\u0001s\u0001t\u0001t\u0001t\u0001t\u0001u\u0001u\u0001"+ - "u\u0001u\u0001u\u0001v\u0001v\u0001v\u0001v\u0001v\u0001w\u0001w\u0001"+ - "w\u0001w\u0001w\u0001x\u0001x\u0001x\u0001x\u0001x\u0001x\u0001x\u0001"+ - "y\u0001y\u0001z\u0004z\u0448\bz\u000bz\fz\u0449\u0001z\u0001z\u0003z\u044e"+ - "\bz\u0001z\u0004z\u0451\bz\u000bz\fz\u0452\u0001{\u0001{\u0001{\u0001"+ - "{\u0001|\u0001|\u0001|\u0001|\u0001}\u0001}\u0001}\u0001}\u0001~\u0001"+ - "~\u0001~\u0001~\u0001\u007f\u0001\u007f\u0001\u007f\u0001\u007f\u0001"+ - "\u0080\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0080\u0001"+ - "\u0081\u0001\u0081\u0001\u0081\u0001\u0081\u0001\u0082\u0001\u0082\u0001"+ - "\u0082\u0001\u0082\u0001\u0083\u0001\u0083\u0001\u0083\u0001\u0083\u0001"+ - "\u0084\u0001\u0084\u0001\u0084\u0001\u0084\u0001\u0085\u0001\u0085\u0001"+ - "\u0085\u0001\u0085\u0001\u0086\u0001\u0086\u0001\u0086\u0001\u0086\u0001"+ - "\u0087\u0001\u0087\u0001\u0087\u0001\u0087\u0001\u0088\u0001\u0088\u0001"+ - "\u0088\u0001\u0088\u0001\u0089\u0001\u0089\u0001\u0089\u0001\u0089\u0001"+ - "\u008a\u0001\u008a\u0001\u008a\u0001\u008a\u0001\u008a\u0001\u008b\u0001"+ - "\u008b\u0001\u008b\u0001\u008b\u0001\u008c\u0001\u008c\u0001\u008c\u0001"+ - "\u008c\u0001\u008d\u0001\u008d\u0001\u008d\u0001\u008d\u0001\u008d\u0001"+ - "\u008e\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008f\u0001\u008f\u0001"+ - "\u008f\u0001\u008f\u0001\u0090\u0001\u0090\u0001\u0090\u0001\u0090\u0001"+ - "\u0091\u0001\u0091\u0001\u0091\u0001\u0091\u0001\u0092\u0001\u0092\u0001"+ - "\u0092\u0001\u0092\u0001\u0092\u0001\u0092\u0001\u0093\u0001\u0093\u0001"+ - "\u0093\u0001\u0093\u0001\u0094\u0001\u0094\u0001\u0094\u0001\u0094\u0001"+ - "\u0095\u0001\u0095\u0001\u0095\u0001\u0095\u0001\u0096\u0001\u0096\u0001"+ - "\u0096\u0001\u0096\u0001\u0097\u0001\u0097\u0001\u0097\u0001\u0097\u0001"+ - "\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0099\u0001\u0099\u0001"+ + "O\u0001O\u0001P\u0001P\u0001P\u0005P\u0372\bP\nP\fP\u0375\tP\u0001P\u0001"+ + "P\u0004P\u0379\bP\u000bP\fP\u037a\u0003P\u037d\bP\u0001Q\u0001Q\u0001"+ + "Q\u0001Q\u0001Q\u0001R\u0001R\u0001R\u0001R\u0001R\u0001S\u0001S\u0005"+ + "S\u038b\bS\nS\fS\u038e\tS\u0001S\u0001S\u0003S\u0392\bS\u0001S\u0004S"+ + "\u0395\bS\u000bS\fS\u0396\u0003S\u0399\bS\u0001T\u0001T\u0004T\u039d\b"+ + "T\u000bT\fT\u039e\u0001T\u0001T\u0001U\u0001U\u0001V\u0001V\u0001V\u0001"+ + "V\u0001W\u0001W\u0001W\u0001W\u0001X\u0001X\u0001X\u0001X\u0001Y\u0001"+ + "Y\u0001Y\u0001Y\u0001Y\u0001Z\u0001Z\u0001Z\u0001Z\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`\u0001a\u0001a\u0001a\u0001"+ + "a\u0001b\u0001b\u0001b\u0001b\u0001c\u0001c\u0001c\u0001c\u0001d\u0001"+ + "d\u0001d\u0001d\u0001d\u0001e\u0001e\u0001e\u0001e\u0001f\u0001f\u0001"+ + "f\u0001f\u0001g\u0001g\u0001g\u0001g\u0003g\u03f4\bg\u0001h\u0001h\u0003"+ + "h\u03f8\bh\u0001h\u0005h\u03fb\bh\nh\fh\u03fe\th\u0001h\u0001h\u0003h"+ + "\u0402\bh\u0001h\u0004h\u0405\bh\u000bh\fh\u0406\u0003h\u0409\bh\u0001"+ + "i\u0001i\u0004i\u040d\bi\u000bi\fi\u040e\u0001j\u0001j\u0001j\u0001j\u0001"+ + "k\u0001k\u0001k\u0001k\u0001l\u0001l\u0001l\u0001l\u0001m\u0001m\u0001"+ + "m\u0001m\u0001m\u0001n\u0001n\u0001n\u0001n\u0001o\u0001o\u0001o\u0001"+ + "o\u0001p\u0001p\u0001p\u0001p\u0001q\u0001q\u0001q\u0001r\u0001r\u0001"+ + "r\u0001r\u0001s\u0001s\u0001s\u0001s\u0001t\u0001t\u0001t\u0001t\u0001"+ + "u\u0001u\u0001u\u0001u\u0001v\u0001v\u0001v\u0001v\u0001v\u0001w\u0001"+ + "w\u0001w\u0001w\u0001w\u0001x\u0001x\u0001x\u0001x\u0001x\u0001y\u0001"+ + "y\u0001y\u0001y\u0001y\u0001y\u0001y\u0001z\u0001z\u0001{\u0004{\u045a"+ + "\b{\u000b{\f{\u045b\u0001{\u0001{\u0003{\u0460\b{\u0001{\u0004{\u0463"+ + "\b{\u000b{\f{\u0464\u0001|\u0001|\u0001|\u0001|\u0001}\u0001}\u0001}\u0001"+ + "}\u0001~\u0001~\u0001~\u0001~\u0001\u007f\u0001\u007f\u0001\u007f\u0001"+ + "\u007f\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0080\u0001\u0081\u0001"+ + "\u0081\u0001\u0081\u0001\u0081\u0001\u0081\u0001\u0081\u0001\u0082\u0001"+ + "\u0082\u0001\u0082\u0001\u0082\u0001\u0083\u0001\u0083\u0001\u0083\u0001"+ + "\u0083\u0001\u0084\u0001\u0084\u0001\u0084\u0001\u0084\u0001\u0085\u0001"+ + "\u0085\u0001\u0085\u0001\u0085\u0001\u0086\u0001\u0086\u0001\u0086\u0001"+ + "\u0086\u0001\u0087\u0001\u0087\u0001\u0087\u0001\u0087\u0001\u0088\u0001"+ + "\u0088\u0001\u0088\u0001\u0088\u0001\u0089\u0001\u0089\u0001\u0089\u0001"+ + "\u0089\u0001\u008a\u0001\u008a\u0001\u008a\u0001\u008a\u0001\u008b\u0001"+ + "\u008b\u0001\u008b\u0001\u008b\u0001\u008b\u0001\u008c\u0001\u008c\u0001"+ + "\u008c\u0001\u008c\u0001\u008d\u0001\u008d\u0001\u008d\u0001\u008d\u0001"+ + "\u008e\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008e\u0001\u008f\u0001"+ + "\u008f\u0001\u008f\u0001\u008f\u0001\u0090\u0001\u0090\u0001\u0090\u0001"+ + "\u0090\u0001\u0091\u0001\u0091\u0001\u0091\u0001\u0091\u0001\u0092\u0001"+ + "\u0092\u0001\u0092\u0001\u0092\u0001\u0093\u0001\u0093\u0001\u0093\u0001"+ + "\u0093\u0001\u0093\u0001\u0093\u0001\u0094\u0001\u0094\u0001\u0094\u0001"+ + "\u0094\u0001\u0095\u0001\u0095\u0001\u0095\u0001\u0095\u0001\u0096\u0001"+ + "\u0096\u0001\u0096\u0001\u0096\u0001\u0097\u0001\u0097\u0001\u0097\u0001"+ + "\u0097\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0099\u0001"+ "\u0099\u0001\u0099\u0001\u0099\u0001\u009a\u0001\u009a\u0001\u009a\u0001"+ - "\u009a\u0001\u009b\u0001\u009b\u0001\u009b\u0001\u009b\u0001\u009c\u0001"+ - "\u009c\u0001\u009c\u0001\u009c\u0001\u009d\u0001\u009d\u0001\u009d\u0001"+ - "\u009d\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009f\u0001"+ - "\u009f\u0001\u009f\u0001\u009f\u0001\u00a0\u0001\u00a0\u0001\u00a0\u0001"+ + "\u009a\u0001\u009a\u0001\u009b\u0001\u009b\u0001\u009b\u0001\u009b\u0001"+ + "\u009c\u0001\u009c\u0001\u009c\u0001\u009c\u0001\u009d\u0001\u009d\u0001"+ + "\u009d\u0001\u009d\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009e\u0001"+ + "\u009f\u0001\u009f\u0001\u009f\u0001\u009f\u0001\u00a0\u0001\u00a0\u0001"+ "\u00a0\u0001\u00a0\u0001\u00a1\u0001\u00a1\u0001\u00a1\u0001\u00a1\u0001"+ - "\u00a1\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a3\u0001"+ - "\u00a3\u0001\u00a3\u0001\u00a3\u0001\u00a4\u0001\u00a4\u0001\u00a4\u0001"+ - "\u00a4\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001"+ - "\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001"+ - "\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a7\u0001\u00a7\u0001"+ - "\u00a7\u0001\u00a7\u0001\u00a8\u0001\u00a8\u0001\u00a8\u0001\u00a8\u0001"+ - "\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00aa\u0001\u00aa\u0001"+ - "\u00aa\u0001\u00aa\u0001\u00aa\u0001\u00ab\u0001\u00ab\u0001\u00ac\u0001"+ - "\u00ac\u0001\u00ac\u0001\u00ac\u0001\u00ac\u0004\u00ac\u052d\b\u00ac\u000b"+ - "\u00ac\f\u00ac\u052e\u0001\u00ad\u0001\u00ad\u0001\u00ad\u0001\u00ad\u0001"+ - "\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00af\u0001\u00af\u0001"+ - "\u00af\u0001\u00af\u0001\u00b0\u0001\u00b0\u0001\u00b0\u0001\u00b0\u0001"+ - "\u00b0\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001"+ - "\u00b1\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b3\u0001"+ - "\u00b3\u0001\u00b3\u0001\u00b3\u0001\u00b4\u0001\u00b4\u0001\u00b4\u0001"+ - "\u00b4\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001"+ - "\u00b5\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b7\u0001"+ - "\u00b7\u0001\u00b7\u0001\u00b7\u0001\u00b8\u0001\u00b8\u0001\u00b8\u0001"+ - "\u00b8\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001"+ - "\u00b9\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001"+ - "\u00ba\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001"+ - "\u00bb\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0002"+ - "\u0252\u02b7\u0000\u00bd\u0010\u0001\u0012\u0002\u0014\u0003\u0016\u0004"+ - "\u0018\u0005\u001a\u0006\u001c\u0007\u001e\b \t\"\n$\u000b&\f(\r*\u000e"+ - ",\u000f.\u00100\u00112\u00124\u00136\u00148\u0015:\u0016<\u0017>\u0018"+ - "@\u0000B\u0019D\u0000F\u0000H\u001aJ\u001bL\u001cN\u001dP\u0000R\u0000"+ - "T\u0000V\u0000X\u0000Z\u0000\\\u0000^\u0000`\u0000b\u0000d\u001ef\u001f"+ - "h j!l\"n#p$r%t&v\'x(z)|*~+\u0080,\u0082-\u0084.\u0086/\u00880\u008a1\u008c"+ + "\u00a1\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001\u00a2\u0001"+ + "\u00a3\u0001\u00a3\u0001\u00a3\u0001\u00a3\u0001\u00a4\u0001\u00a4\u0001"+ + "\u00a4\u0001\u00a4\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001\u00a5\u0001"+ + "\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a6\u0001\u00a7\u0001"+ + "\u00a7\u0001\u00a7\u0001\u00a7\u0001\u00a7\u0001\u00a7\u0001\u00a7\u0001"+ + "\u00a7\u0001\u00a7\u0001\u00a7\u0001\u00a8\u0001\u00a8\u0001\u00a8\u0001"+ + "\u00a8\u0001\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00a9\u0001\u00aa\u0001"+ + "\u00aa\u0001\u00aa\u0001\u00aa\u0001\u00ab\u0001\u00ab\u0001\u00ab\u0001"+ + "\u00ab\u0001\u00ab\u0001\u00ac\u0001\u00ac\u0001\u00ad\u0001\u00ad\u0001"+ + "\u00ad\u0001\u00ad\u0001\u00ad\u0004\u00ad\u053f\b\u00ad\u000b\u00ad\f"+ + "\u00ad\u0540\u0001\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00ae\u0001\u00af"+ + "\u0001\u00af\u0001\u00af\u0001\u00af\u0001\u00b0\u0001\u00b0\u0001\u00b0"+ + "\u0001\u00b0\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1\u0001\u00b1"+ + "\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2\u0001\u00b2"+ + "\u0001\u00b3\u0001\u00b3\u0001\u00b3\u0001\u00b3\u0001\u00b4\u0001\u00b4"+ + "\u0001\u00b4\u0001\u00b4\u0001\u00b5\u0001\u00b5\u0001\u00b5\u0001\u00b5"+ + "\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b6\u0001\u00b6"+ + "\u0001\u00b7\u0001\u00b7\u0001\u00b7\u0001\u00b7\u0001\u00b8\u0001\u00b8"+ + "\u0001\u00b8\u0001\u00b8\u0001\u00b9\u0001\u00b9\u0001\u00b9\u0001\u00b9"+ + "\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba\u0001\u00ba"+ + "\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb\u0001\u00bb"+ + "\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc\u0001\u00bc"+ + "\u0001\u00bd\u0001\u00bd\u0001\u00bd\u0001\u00bd\u0001\u00bd\u0002\u0254"+ + "\u02b9\u0000\u00be\u0010\u0001\u0012\u0002\u0014\u0003\u0016\u0004\u0018"+ + "\u0005\u001a\u0006\u001c\u0007\u001e\b \t\"\n$\u000b&\f(\r*\u000e,\u000f"+ + ".\u00100\u00112\u00124\u00136\u00148\u0015:\u0016<\u0017>\u0018@\u0000"+ + "B\u0019D\u0000F\u0000H\u001aJ\u001bL\u001cN\u001dP\u0000R\u0000T\u0000"+ + "V\u0000X\u0000Z\u0000\\\u0000^\u0000`\u0000b\u0000d\u001ef\u001fh j!l"+ + "\"n#p$r%t&v\'x(z)|*~+\u0080,\u0082-\u0084.\u0086/\u00880\u008a1\u008c"+ "2\u008e3\u00904\u00925\u00946\u00967\u00988\u009a9\u009c:\u009e;\u00a0"+ "<\u00a2=\u00a4>\u00a6?\u00a8@\u00aaA\u00acB\u00aeC\u00b0D\u00b2E\u00b4"+ - "F\u00b6\u0000\u00b8G\u00baH\u00bcI\u00beJ\u00c0\u0000\u00c2\u0000\u00c4"+ - "\u0000\u00c6\u0000\u00c8\u0000\u00ca\u0000\u00ccK\u00ce\u0000\u00d0L\u00d2"+ - "M\u00d4N\u00d6\u0000\u00d8\u0000\u00da\u0000\u00dc\u0000\u00de\u0000\u00e0"+ - "O\u00e2P\u00e4Q\u00e6R\u00e8\u0000\u00ea\u0000\u00ec\u0000\u00ee\u0000"+ - "\u00f0S\u00f2\u0000\u00f4T\u00f6U\u00f8V\u00fa\u0000\u00fc\u0000\u00fe"+ - "W\u0100X\u0102\u0000\u0104Y\u0106\u0000\u0108\u0000\u010aZ\u010c[\u010e"+ - "\\\u0110\u0000\u0112\u0000\u0114\u0000\u0116\u0000\u0118\u0000\u011a\u0000"+ - "\u011c\u0000\u011e]\u0120^\u0122_\u0124\u0000\u0126\u0000\u0128\u0000"+ - "\u012a\u0000\u012c\u0000\u012e`\u0130a\u0132b\u0134\u0000\u0136\u0000"+ - "\u0138\u0000\u013a\u0000\u013cc\u013ed\u0140e\u0142\u0000\u0144\u0000"+ - "\u0146\u0000\u0148\u0000\u014af\u014cg\u014eh\u0150\u0000\u0152i\u0154"+ - "j\u0156k\u0158l\u015a\u0000\u015cm\u015en\u0160o\u0162p\u0164\u0000\u0166"+ - "q\u0168r\u016as\u016ct\u016eu\u0170\u0000\u0172\u0000\u0174v\u0176w\u0178"+ - "x\u017a\u0000\u017cy\u017ez\u0180{\u0182\u0000\u0184\u0000\u0186\u0000"+ - "\u0188\u0000\u0010\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t"+ - "\n\u000b\f\r\u000e\u000f\r\u0006\u0000\t\n\r\r //[[]]\u0002\u0000\n\n"+ - "\r\r\u0003\u0000\t\n\r\r \n\u0000\t\n\r\r ,,//==[[]]``||\u0002\u0000"+ - "**//\u0001\u000009\u0002\u0000AZaz\u0005\u0000\"\"\\\\nnrrtt\u0004\u0000"+ - "\n\n\r\r\"\"\\\\\u0002\u0000EEee\u0002\u0000++--\u0001\u0000``\u000b\u0000"+ - "\t\n\r\r \"#,,//::<<>?\\\\||\u0593\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\u0000"+ - "0\u0001\u0000\u0000\u0000\u00002\u0001\u0000\u0000\u0000\u00004\u0001"+ - "\u0000\u0000\u0000\u00006\u0001\u0000\u0000\u0000\u00008\u0001\u0000\u0000"+ - "\u0000\u0000:\u0001\u0000\u0000\u0000\u0000<\u0001\u0000\u0000\u0000\u0000"+ - ">\u0001\u0000\u0000\u0000\u0000B\u0001\u0000\u0000\u0000\u0001D\u0001"+ - "\u0000\u0000\u0000\u0001F\u0001\u0000\u0000\u0000\u0001H\u0001\u0000\u0000"+ - "\u0000\u0001J\u0001\u0000\u0000\u0000\u0001L\u0001\u0000\u0000\u0000\u0002"+ - "N\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\u0002"+ - "p\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\u0002\u00a0\u0001\u0000\u0000\u0000\u0002\u00a2"+ - "\u0001\u0000\u0000\u0000\u0002\u00a4\u0001\u0000\u0000\u0000\u0002\u00a6"+ - "\u0001\u0000\u0000\u0000\u0002\u00a8\u0001\u0000\u0000\u0000\u0002\u00aa"+ - "\u0001\u0000\u0000\u0000\u0002\u00ac\u0001\u0000\u0000\u0000\u0002\u00ae"+ - "\u0001\u0000\u0000\u0000\u0002\u00b0\u0001\u0000\u0000\u0000\u0002\u00b2"+ - "\u0001\u0000\u0000\u0000\u0002\u00b4\u0001\u0000\u0000\u0000\u0002\u00b8"+ - "\u0001\u0000\u0000\u0000\u0002\u00ba\u0001\u0000\u0000\u0000\u0002\u00bc"+ - "\u0001\u0000\u0000\u0000\u0002\u00be\u0001\u0000\u0000\u0000\u0003\u00c0"+ - "\u0001\u0000\u0000\u0000\u0003\u00c2\u0001\u0000\u0000\u0000\u0003\u00c4"+ - "\u0001\u0000\u0000\u0000\u0003\u00c6\u0001\u0000\u0000\u0000\u0003\u00c8"+ - "\u0001\u0000\u0000\u0000\u0003\u00ca\u0001\u0000\u0000\u0000\u0003\u00cc"+ - "\u0001\u0000\u0000\u0000\u0003\u00ce\u0001\u0000\u0000\u0000\u0003\u00d0"+ - "\u0001\u0000\u0000\u0000\u0003\u00d2\u0001\u0000\u0000\u0000\u0003\u00d4"+ - "\u0001\u0000\u0000\u0000\u0004\u00d6\u0001\u0000\u0000\u0000\u0004\u00d8"+ - "\u0001\u0000\u0000\u0000\u0004\u00da\u0001\u0000\u0000\u0000\u0004\u00e0"+ - "\u0001\u0000\u0000\u0000\u0004\u00e2\u0001\u0000\u0000\u0000\u0004\u00e4"+ - "\u0001\u0000\u0000\u0000\u0004\u00e6\u0001\u0000\u0000\u0000\u0005\u00e8"+ - "\u0001\u0000\u0000\u0000\u0005\u00ea\u0001\u0000\u0000\u0000\u0005\u00ec"+ - "\u0001\u0000\u0000\u0000\u0005\u00ee\u0001\u0000\u0000\u0000\u0005\u00f0"+ - "\u0001\u0000\u0000\u0000\u0005\u00f2\u0001\u0000\u0000\u0000\u0005\u00f4"+ - "\u0001\u0000\u0000\u0000\u0005\u00f6\u0001\u0000\u0000\u0000\u0005\u00f8"+ - "\u0001\u0000\u0000\u0000\u0006\u00fa\u0001\u0000\u0000\u0000\u0006\u00fc"+ - "\u0001\u0000\u0000\u0000\u0006\u00fe\u0001\u0000\u0000\u0000\u0006\u0100"+ - "\u0001\u0000\u0000\u0000\u0006\u0104\u0001\u0000\u0000\u0000\u0006\u0106"+ - "\u0001\u0000\u0000\u0000\u0006\u0108\u0001\u0000\u0000\u0000\u0006\u010a"+ - "\u0001\u0000\u0000\u0000\u0006\u010c\u0001\u0000\u0000\u0000\u0006\u010e"+ - "\u0001\u0000\u0000\u0000\u0007\u0110\u0001\u0000\u0000\u0000\u0007\u0112"+ - "\u0001\u0000\u0000\u0000\u0007\u0114\u0001\u0000\u0000\u0000\u0007\u0116"+ - "\u0001\u0000\u0000\u0000\u0007\u0118\u0001\u0000\u0000\u0000\u0007\u011a"+ - "\u0001\u0000\u0000\u0000\u0007\u011c\u0001\u0000\u0000\u0000\u0007\u011e"+ - "\u0001\u0000\u0000\u0000\u0007\u0120\u0001\u0000\u0000\u0000\u0007\u0122"+ - "\u0001\u0000\u0000\u0000\b\u0124\u0001\u0000\u0000\u0000\b\u0126\u0001"+ - "\u0000\u0000\u0000\b\u0128\u0001\u0000\u0000\u0000\b\u012a\u0001\u0000"+ - "\u0000\u0000\b\u012c\u0001\u0000\u0000\u0000\b\u012e\u0001\u0000\u0000"+ - "\u0000\b\u0130\u0001\u0000\u0000\u0000\b\u0132\u0001\u0000\u0000\u0000"+ - "\t\u0134\u0001\u0000\u0000\u0000\t\u0136\u0001\u0000\u0000\u0000\t\u0138"+ - "\u0001\u0000\u0000\u0000\t\u013a\u0001\u0000\u0000\u0000\t\u013c\u0001"+ - "\u0000\u0000\u0000\t\u013e\u0001\u0000\u0000\u0000\t\u0140\u0001\u0000"+ - "\u0000\u0000\n\u0142\u0001\u0000\u0000\u0000\n\u0144\u0001\u0000\u0000"+ - "\u0000\n\u0146\u0001\u0000\u0000\u0000\n\u0148\u0001\u0000\u0000\u0000"+ - "\n\u014a\u0001\u0000\u0000\u0000\n\u014c\u0001\u0000\u0000\u0000\n\u014e"+ - "\u0001\u0000\u0000\u0000\u000b\u0150\u0001\u0000\u0000\u0000\u000b\u0152"+ - "\u0001\u0000\u0000\u0000\u000b\u0154\u0001\u0000\u0000\u0000\u000b\u0156"+ - "\u0001\u0000\u0000\u0000\u000b\u0158\u0001\u0000\u0000\u0000\f\u015a\u0001"+ - "\u0000\u0000\u0000\f\u015c\u0001\u0000\u0000\u0000\f\u015e\u0001\u0000"+ - "\u0000\u0000\f\u0160\u0001\u0000\u0000\u0000\f\u0162\u0001\u0000\u0000"+ - "\u0000\r\u0164\u0001\u0000\u0000\u0000\r\u0166\u0001\u0000\u0000\u0000"+ - "\r\u0168\u0001\u0000\u0000\u0000\r\u016a\u0001\u0000\u0000\u0000\r\u016c"+ - "\u0001\u0000\u0000\u0000\r\u016e\u0001\u0000\u0000\u0000\u000e\u0170\u0001"+ - "\u0000\u0000\u0000\u000e\u0172\u0001\u0000\u0000\u0000\u000e\u0174\u0001"+ - "\u0000\u0000\u0000\u000e\u0176\u0001\u0000\u0000\u0000\u000e\u0178\u0001"+ - "\u0000\u0000\u0000\u000f\u017a\u0001\u0000\u0000\u0000\u000f\u017c\u0001"+ - "\u0000\u0000\u0000\u000f\u017e\u0001\u0000\u0000\u0000\u000f\u0180\u0001"+ - "\u0000\u0000\u0000\u000f\u0182\u0001\u0000\u0000\u0000\u000f\u0184\u0001"+ - "\u0000\u0000\u0000\u000f\u0186\u0001\u0000\u0000\u0000\u000f\u0188\u0001"+ - "\u0000\u0000\u0000\u0010\u018a\u0001\u0000\u0000\u0000\u0012\u0194\u0001"+ - "\u0000\u0000\u0000\u0014\u019b\u0001\u0000\u0000\u0000\u0016\u01a4\u0001"+ - "\u0000\u0000\u0000\u0018\u01ab\u0001\u0000\u0000\u0000\u001a\u01b5\u0001"+ - "\u0000\u0000\u0000\u001c\u01bc\u0001\u0000\u0000\u0000\u001e\u01c3\u0001"+ - "\u0000\u0000\u0000 \u01d1\u0001\u0000\u0000\u0000\"\u01d8\u0001\u0000"+ - "\u0000\u0000$\u01e0\u0001\u0000\u0000\u0000&\u01e9\u0001\u0000\u0000\u0000"+ - "(\u01f0\u0001\u0000\u0000\u0000*\u01fa\u0001\u0000\u0000\u0000,\u0206"+ - "\u0001\u0000\u0000\u0000.\u020f\u0001\u0000\u0000\u00000\u0215\u0001\u0000"+ - "\u0000\u00002\u021c\u0001\u0000\u0000\u00004\u0223\u0001\u0000\u0000\u0000"+ - "6\u022b\u0001\u0000\u0000\u00008\u0234\u0001\u0000\u0000\u0000:\u023a"+ - "\u0001\u0000\u0000\u0000<\u024b\u0001\u0000\u0000\u0000>\u025b\u0001\u0000"+ - "\u0000\u0000@\u0264\u0001\u0000\u0000\u0000B\u0267\u0001\u0000\u0000\u0000"+ - "D\u026b\u0001\u0000\u0000\u0000F\u0270\u0001\u0000\u0000\u0000H\u0275"+ - "\u0001\u0000\u0000\u0000J\u0279\u0001\u0000\u0000\u0000L\u027d\u0001\u0000"+ - "\u0000\u0000N\u0281\u0001\u0000\u0000\u0000P\u0285\u0001\u0000\u0000\u0000"+ - "R\u0287\u0001\u0000\u0000\u0000T\u0289\u0001\u0000\u0000\u0000V\u028c"+ - "\u0001\u0000\u0000\u0000X\u028e\u0001\u0000\u0000\u0000Z\u0297\u0001\u0000"+ - "\u0000\u0000\\\u0299\u0001\u0000\u0000\u0000^\u029e\u0001\u0000\u0000"+ - "\u0000`\u02a0\u0001\u0000\u0000\u0000b\u02a5\u0001\u0000\u0000\u0000d"+ - "\u02c4\u0001\u0000\u0000\u0000f\u02c7\u0001\u0000\u0000\u0000h\u02f5\u0001"+ - "\u0000\u0000\u0000j\u02f7\u0001\u0000\u0000\u0000l\u02fa\u0001\u0000\u0000"+ - "\u0000n\u02fe\u0001\u0000\u0000\u0000p\u0302\u0001\u0000\u0000\u0000r"+ - "\u0304\u0001\u0000\u0000\u0000t\u0307\u0001\u0000\u0000\u0000v\u0309\u0001"+ - "\u0000\u0000\u0000x\u030e\u0001\u0000\u0000\u0000z\u0310\u0001\u0000\u0000"+ - "\u0000|\u0316\u0001\u0000\u0000\u0000~\u031c\u0001\u0000\u0000\u0000\u0080"+ - "\u0321\u0001\u0000\u0000\u0000\u0082\u0323\u0001\u0000\u0000\u0000\u0084"+ - "\u0326\u0001\u0000\u0000\u0000\u0086\u0329\u0001\u0000\u0000\u0000\u0088"+ - "\u032e\u0001\u0000\u0000\u0000\u008a\u0332\u0001\u0000\u0000\u0000\u008c"+ - "\u0337\u0001\u0000\u0000\u0000\u008e\u033d\u0001\u0000\u0000\u0000\u0090"+ - "\u0340\u0001\u0000\u0000\u0000\u0092\u0342\u0001\u0000\u0000\u0000\u0094"+ - "\u0348\u0001\u0000\u0000\u0000\u0096\u034a\u0001\u0000\u0000\u0000\u0098"+ - "\u034f\u0001\u0000\u0000\u0000\u009a\u0352\u0001\u0000\u0000\u0000\u009c"+ - "\u0355\u0001\u0000\u0000\u0000\u009e\u0358\u0001\u0000\u0000\u0000\u00a0"+ - "\u035a\u0001\u0000\u0000\u0000\u00a2\u035d\u0001\u0000\u0000\u0000\u00a4"+ - "\u035f\u0001\u0000\u0000\u0000\u00a6\u0362\u0001\u0000\u0000\u0000\u00a8"+ - "\u0364\u0001\u0000\u0000\u0000\u00aa\u0366\u0001\u0000\u0000\u0000\u00ac"+ - "\u0368\u0001\u0000\u0000\u0000\u00ae\u036a\u0001\u0000\u0000\u0000\u00b0"+ - "\u036c\u0001\u0000\u0000\u0000\u00b2\u0371\u0001\u0000\u0000\u0000\u00b4"+ - "\u0386\u0001\u0000\u0000\u0000\u00b6\u0388\u0001\u0000\u0000\u0000\u00b8"+ - "\u0390\u0001\u0000\u0000\u0000\u00ba\u0392\u0001\u0000\u0000\u0000\u00bc"+ - "\u0396\u0001\u0000\u0000\u0000\u00be\u039a\u0001\u0000\u0000\u0000\u00c0"+ - "\u039e\u0001\u0000\u0000\u0000\u00c2\u03a3\u0001\u0000\u0000\u0000\u00c4"+ - "\u03a7\u0001\u0000\u0000\u0000\u00c6\u03ab\u0001\u0000\u0000\u0000\u00c8"+ - "\u03af\u0001\u0000\u0000\u0000\u00ca\u03b3\u0001\u0000\u0000\u0000\u00cc"+ - "\u03b7\u0001\u0000\u0000\u0000\u00ce\u03c0\u0001\u0000\u0000\u0000\u00d0"+ - "\u03c4\u0001\u0000\u0000\u0000\u00d2\u03c8\u0001\u0000\u0000\u0000\u00d4"+ - "\u03cc\u0001\u0000\u0000\u0000\u00d6\u03d0\u0001\u0000\u0000\u0000\u00d8"+ - "\u03d5\u0001\u0000\u0000\u0000\u00da\u03d9\u0001\u0000\u0000\u0000\u00dc"+ - "\u03e1\u0001\u0000\u0000\u0000\u00de\u03f6\u0001\u0000\u0000\u0000\u00e0"+ - "\u03fa\u0001\u0000\u0000\u0000\u00e2\u03fe\u0001\u0000\u0000\u0000\u00e4"+ - "\u0402\u0001\u0000\u0000\u0000\u00e6\u0406\u0001\u0000\u0000\u0000\u00e8"+ - "\u040a\u0001\u0000\u0000\u0000\u00ea\u040f\u0001\u0000\u0000\u0000\u00ec"+ - "\u0413\u0001\u0000\u0000\u0000\u00ee\u0417\u0001\u0000\u0000\u0000\u00f0"+ - "\u041b\u0001\u0000\u0000\u0000\u00f2\u041e\u0001\u0000\u0000\u0000\u00f4"+ - "\u0422\u0001\u0000\u0000\u0000\u00f6\u0426\u0001\u0000\u0000\u0000\u00f8"+ - "\u042a\u0001\u0000\u0000\u0000\u00fa\u042e\u0001\u0000\u0000\u0000\u00fc"+ - "\u0433\u0001\u0000\u0000\u0000\u00fe\u0438\u0001\u0000\u0000\u0000\u0100"+ - "\u043d\u0001\u0000\u0000\u0000\u0102\u0444\u0001\u0000\u0000\u0000\u0104"+ - "\u044d\u0001\u0000\u0000\u0000\u0106\u0454\u0001\u0000\u0000\u0000\u0108"+ - "\u0458\u0001\u0000\u0000\u0000\u010a\u045c\u0001\u0000\u0000\u0000\u010c"+ - "\u0460\u0001\u0000\u0000\u0000\u010e\u0464\u0001\u0000\u0000\u0000\u0110"+ - "\u0468\u0001\u0000\u0000\u0000\u0112\u046e\u0001\u0000\u0000\u0000\u0114"+ - "\u0472\u0001\u0000\u0000\u0000\u0116\u0476\u0001\u0000\u0000\u0000\u0118"+ - "\u047a\u0001\u0000\u0000\u0000\u011a\u047e\u0001\u0000\u0000\u0000\u011c"+ - "\u0482\u0001\u0000\u0000\u0000\u011e\u0486\u0001\u0000\u0000\u0000\u0120"+ - "\u048a\u0001\u0000\u0000\u0000\u0122\u048e\u0001\u0000\u0000\u0000\u0124"+ - "\u0492\u0001\u0000\u0000\u0000\u0126\u0497\u0001\u0000\u0000\u0000\u0128"+ - "\u049b\u0001\u0000\u0000\u0000\u012a\u049f\u0001\u0000\u0000\u0000\u012c"+ - "\u04a4\u0001\u0000\u0000\u0000\u012e\u04a8\u0001\u0000\u0000\u0000\u0130"+ - "\u04ac\u0001\u0000\u0000\u0000\u0132\u04b0\u0001\u0000\u0000\u0000\u0134"+ - "\u04b4\u0001\u0000\u0000\u0000\u0136\u04ba\u0001\u0000\u0000\u0000\u0138"+ - "\u04be\u0001\u0000\u0000\u0000\u013a\u04c2\u0001\u0000\u0000\u0000\u013c"+ - "\u04c6\u0001\u0000\u0000\u0000\u013e\u04ca\u0001\u0000\u0000\u0000\u0140"+ - "\u04ce\u0001\u0000\u0000\u0000\u0142\u04d2\u0001\u0000\u0000\u0000\u0144"+ - "\u04d7\u0001\u0000\u0000\u0000\u0146\u04db\u0001\u0000\u0000\u0000\u0148"+ - "\u04df\u0001\u0000\u0000\u0000\u014a\u04e3\u0001\u0000\u0000\u0000\u014c"+ - "\u04e7\u0001\u0000\u0000\u0000\u014e\u04eb\u0001\u0000\u0000\u0000\u0150"+ - "\u04ef\u0001\u0000\u0000\u0000\u0152\u04f4\u0001\u0000\u0000\u0000\u0154"+ - "\u04f9\u0001\u0000\u0000\u0000\u0156\u04fd\u0001\u0000\u0000\u0000\u0158"+ - "\u0501\u0001\u0000\u0000\u0000\u015a\u0505\u0001\u0000\u0000\u0000\u015c"+ - "\u050a\u0001\u0000\u0000\u0000\u015e\u0514\u0001\u0000\u0000\u0000\u0160"+ - "\u0518\u0001\u0000\u0000\u0000\u0162\u051c\u0001\u0000\u0000\u0000\u0164"+ - "\u0520\u0001\u0000\u0000\u0000\u0166\u0525\u0001\u0000\u0000\u0000\u0168"+ - "\u052c\u0001\u0000\u0000\u0000\u016a\u0530\u0001\u0000\u0000\u0000\u016c"+ - "\u0534\u0001\u0000\u0000\u0000\u016e\u0538\u0001\u0000\u0000\u0000\u0170"+ - "\u053c\u0001\u0000\u0000\u0000\u0172\u0541\u0001\u0000\u0000\u0000\u0174"+ - "\u0547\u0001\u0000\u0000\u0000\u0176\u054b\u0001\u0000\u0000\u0000\u0178"+ - "\u054f\u0001\u0000\u0000\u0000\u017a\u0553\u0001\u0000\u0000\u0000\u017c"+ - "\u0559\u0001\u0000\u0000\u0000\u017e\u055d\u0001\u0000\u0000\u0000\u0180"+ - "\u0561\u0001\u0000\u0000\u0000\u0182\u0565\u0001\u0000\u0000\u0000\u0184"+ - "\u056b\u0001\u0000\u0000\u0000\u0186\u0571\u0001\u0000\u0000\u0000\u0188"+ - "\u0577\u0001\u0000\u0000\u0000\u018a\u018b\u0005d\u0000\u0000\u018b\u018c"+ - "\u0005i\u0000\u0000\u018c\u018d\u0005s\u0000\u0000\u018d\u018e\u0005s"+ - "\u0000\u0000\u018e\u018f\u0005e\u0000\u0000\u018f\u0190\u0005c\u0000\u0000"+ - "\u0190\u0191\u0005t\u0000\u0000\u0191\u0192\u0001\u0000\u0000\u0000\u0192"+ - "\u0193\u0006\u0000\u0000\u0000\u0193\u0011\u0001\u0000\u0000\u0000\u0194"+ - "\u0195\u0005d\u0000\u0000\u0195\u0196\u0005r\u0000\u0000\u0196\u0197\u0005"+ - "o\u0000\u0000\u0197\u0198\u0005p\u0000\u0000\u0198\u0199\u0001\u0000\u0000"+ - "\u0000\u0199\u019a\u0006\u0001\u0001\u0000\u019a\u0013\u0001\u0000\u0000"+ - "\u0000\u019b\u019c\u0005e\u0000\u0000\u019c\u019d\u0005n\u0000\u0000\u019d"+ - "\u019e\u0005r\u0000\u0000\u019e\u019f\u0005i\u0000\u0000\u019f\u01a0\u0005"+ - "c\u0000\u0000\u01a0\u01a1\u0005h\u0000\u0000\u01a1\u01a2\u0001\u0000\u0000"+ - "\u0000\u01a2\u01a3\u0006\u0002\u0002\u0000\u01a3\u0015\u0001\u0000\u0000"+ - "\u0000\u01a4\u01a5\u0005e\u0000\u0000\u01a5\u01a6\u0005v\u0000\u0000\u01a6"+ - "\u01a7\u0005a\u0000\u0000\u01a7\u01a8\u0005l\u0000\u0000\u01a8\u01a9\u0001"+ - "\u0000\u0000\u0000\u01a9\u01aa\u0006\u0003\u0000\u0000\u01aa\u0017\u0001"+ - "\u0000\u0000\u0000\u01ab\u01ac\u0005e\u0000\u0000\u01ac\u01ad\u0005x\u0000"+ - "\u0000\u01ad\u01ae\u0005p\u0000\u0000\u01ae\u01af\u0005l\u0000\u0000\u01af"+ - "\u01b0\u0005a\u0000\u0000\u01b0\u01b1\u0005i\u0000\u0000\u01b1\u01b2\u0005"+ - "n\u0000\u0000\u01b2\u01b3\u0001\u0000\u0000\u0000\u01b3\u01b4\u0006\u0004"+ - "\u0003\u0000\u01b4\u0019\u0001\u0000\u0000\u0000\u01b5\u01b6\u0005f\u0000"+ - "\u0000\u01b6\u01b7\u0005r\u0000\u0000\u01b7\u01b8\u0005o\u0000\u0000\u01b8"+ - "\u01b9\u0005m\u0000\u0000\u01b9\u01ba\u0001\u0000\u0000\u0000\u01ba\u01bb"+ - "\u0006\u0005\u0004\u0000\u01bb\u001b\u0001\u0000\u0000\u0000\u01bc\u01bd"+ - "\u0005g\u0000\u0000\u01bd\u01be\u0005r\u0000\u0000\u01be\u01bf\u0005o"+ - "\u0000\u0000\u01bf\u01c0\u0005k\u0000\u0000\u01c0\u01c1\u0001\u0000\u0000"+ - "\u0000\u01c1\u01c2\u0006\u0006\u0000\u0000\u01c2\u001d\u0001\u0000\u0000"+ - "\u0000\u01c3\u01c4\u0005i\u0000\u0000\u01c4\u01c5\u0005n\u0000\u0000\u01c5"+ - "\u01c6\u0005l\u0000\u0000\u01c6\u01c7\u0005i\u0000\u0000\u01c7\u01c8\u0005"+ - "n\u0000\u0000\u01c8\u01c9\u0005e\u0000\u0000\u01c9\u01ca\u0005s\u0000"+ - "\u0000\u01ca\u01cb\u0005t\u0000\u0000\u01cb\u01cc\u0005a\u0000\u0000\u01cc"+ - "\u01cd\u0005t\u0000\u0000\u01cd\u01ce\u0005s\u0000\u0000\u01ce\u01cf\u0001"+ - "\u0000\u0000\u0000\u01cf\u01d0\u0006\u0007\u0000\u0000\u01d0\u001f\u0001"+ - "\u0000\u0000\u0000\u01d1\u01d2\u0005k\u0000\u0000\u01d2\u01d3\u0005e\u0000"+ - "\u0000\u01d3\u01d4\u0005e\u0000\u0000\u01d4\u01d5\u0005p\u0000\u0000\u01d5"+ - "\u01d6\u0001\u0000\u0000\u0000\u01d6\u01d7\u0006\b\u0001\u0000\u01d7!"+ - "\u0001\u0000\u0000\u0000\u01d8\u01d9\u0005l\u0000\u0000\u01d9\u01da\u0005"+ - "i\u0000\u0000\u01da\u01db\u0005m\u0000\u0000\u01db\u01dc\u0005i\u0000"+ - "\u0000\u01dc\u01dd\u0005t\u0000\u0000\u01dd\u01de\u0001\u0000\u0000\u0000"+ - "\u01de\u01df\u0006\t\u0000\u0000\u01df#\u0001\u0000\u0000\u0000\u01e0"+ - "\u01e1\u0005l\u0000\u0000\u01e1\u01e2\u0005o\u0000\u0000\u01e2\u01e3\u0005"+ - "o\u0000\u0000\u01e3\u01e4\u0005k\u0000\u0000\u01e4\u01e5\u0005u\u0000"+ - "\u0000\u01e5\u01e6\u0005p\u0000\u0000\u01e6\u01e7\u0001\u0000\u0000\u0000"+ - "\u01e7\u01e8\u0006\n\u0005\u0000\u01e8%\u0001\u0000\u0000\u0000\u01e9"+ - "\u01ea\u0005m\u0000\u0000\u01ea\u01eb\u0005e\u0000\u0000\u01eb\u01ec\u0005"+ - "t\u0000\u0000\u01ec\u01ed\u0005a\u0000\u0000\u01ed\u01ee\u0001\u0000\u0000"+ - "\u0000\u01ee\u01ef\u0006\u000b\u0006\u0000\u01ef\'\u0001\u0000\u0000\u0000"+ - "\u01f0\u01f1\u0005m\u0000\u0000\u01f1\u01f2\u0005e\u0000\u0000\u01f2\u01f3"+ - "\u0005t\u0000\u0000\u01f3\u01f4\u0005r\u0000\u0000\u01f4\u01f5\u0005i"+ - "\u0000\u0000\u01f5\u01f6\u0005c\u0000\u0000\u01f6\u01f7\u0005s\u0000\u0000"+ - "\u01f7\u01f8\u0001\u0000\u0000\u0000\u01f8\u01f9\u0006\f\u0007\u0000\u01f9"+ - ")\u0001\u0000\u0000\u0000\u01fa\u01fb\u0005m\u0000\u0000\u01fb\u01fc\u0005"+ - "v\u0000\u0000\u01fc\u01fd\u0005_\u0000\u0000\u01fd\u01fe\u0005e\u0000"+ - "\u0000\u01fe\u01ff\u0005x\u0000\u0000\u01ff\u0200\u0005p\u0000\u0000\u0200"+ - "\u0201\u0005a\u0000\u0000\u0201\u0202\u0005n\u0000\u0000\u0202\u0203\u0005"+ - "d\u0000\u0000\u0203\u0204\u0001\u0000\u0000\u0000\u0204\u0205\u0006\r"+ - "\b\u0000\u0205+\u0001\u0000\u0000\u0000\u0206\u0207\u0005r\u0000\u0000"+ - "\u0207\u0208\u0005e\u0000\u0000\u0208\u0209\u0005n\u0000\u0000\u0209\u020a"+ - "\u0005a\u0000\u0000\u020a\u020b\u0005m\u0000\u0000\u020b\u020c\u0005e"+ - "\u0000\u0000\u020c\u020d\u0001\u0000\u0000\u0000\u020d\u020e\u0006\u000e"+ - "\t\u0000\u020e-\u0001\u0000\u0000\u0000\u020f\u0210\u0005r\u0000\u0000"+ - "\u0210\u0211\u0005o\u0000\u0000\u0211\u0212\u0005w\u0000\u0000\u0212\u0213"+ - "\u0001\u0000\u0000\u0000\u0213\u0214\u0006\u000f\u0000\u0000\u0214/\u0001"+ - "\u0000\u0000\u0000\u0215\u0216\u0005s\u0000\u0000\u0216\u0217\u0005h\u0000"+ - "\u0000\u0217\u0218\u0005o\u0000\u0000\u0218\u0219\u0005w\u0000\u0000\u0219"+ - "\u021a\u0001\u0000\u0000\u0000\u021a\u021b\u0006\u0010\n\u0000\u021b1"+ - "\u0001\u0000\u0000\u0000\u021c\u021d\u0005s\u0000\u0000\u021d\u021e\u0005"+ - "o\u0000\u0000\u021e\u021f\u0005r\u0000\u0000\u021f\u0220\u0005t\u0000"+ - "\u0000\u0220\u0221\u0001\u0000\u0000\u0000\u0221\u0222\u0006\u0011\u0000"+ - "\u0000\u02223\u0001\u0000\u0000\u0000\u0223\u0224\u0005s\u0000\u0000\u0224"+ - "\u0225\u0005t\u0000\u0000\u0225\u0226\u0005a\u0000\u0000\u0226\u0227\u0005"+ - "t\u0000\u0000\u0227\u0228\u0005s\u0000\u0000\u0228\u0229\u0001\u0000\u0000"+ - "\u0000\u0229\u022a\u0006\u0012\u0000\u0000\u022a5\u0001\u0000\u0000\u0000"+ - "\u022b\u022c\u0005w\u0000\u0000\u022c\u022d\u0005h\u0000\u0000\u022d\u022e"+ - "\u0005e\u0000\u0000\u022e\u022f\u0005r\u0000\u0000\u022f\u0230\u0005e"+ - "\u0000\u0000\u0230\u0231\u0001\u0000\u0000\u0000\u0231\u0232\u0006\u0013"+ - "\u0000\u0000\u02327\u0001\u0000\u0000\u0000\u0233\u0235\b\u0000\u0000"+ - "\u0000\u0234\u0233\u0001\u0000\u0000\u0000\u0235\u0236\u0001\u0000\u0000"+ - "\u0000\u0236\u0234\u0001\u0000\u0000\u0000\u0236\u0237\u0001\u0000\u0000"+ - "\u0000\u0237\u0238\u0001\u0000\u0000\u0000\u0238\u0239\u0006\u0014\u0000"+ - "\u0000\u02399\u0001\u0000\u0000\u0000\u023a\u023b\u0005/\u0000\u0000\u023b"+ - "\u023c\u0005/\u0000\u0000\u023c\u0240\u0001\u0000\u0000\u0000\u023d\u023f"+ - "\b\u0001\u0000\u0000\u023e\u023d\u0001\u0000\u0000\u0000\u023f\u0242\u0001"+ - "\u0000\u0000\u0000\u0240\u023e\u0001\u0000\u0000\u0000\u0240\u0241\u0001"+ - "\u0000\u0000\u0000\u0241\u0244\u0001\u0000\u0000\u0000\u0242\u0240\u0001"+ - "\u0000\u0000\u0000\u0243\u0245\u0005\r\u0000\u0000\u0244\u0243\u0001\u0000"+ - "\u0000\u0000\u0244\u0245\u0001\u0000\u0000\u0000\u0245\u0247\u0001\u0000"+ - "\u0000\u0000\u0246\u0248\u0005\n\u0000\u0000\u0247\u0246\u0001\u0000\u0000"+ - "\u0000\u0247\u0248\u0001\u0000\u0000\u0000\u0248\u0249\u0001\u0000\u0000"+ - "\u0000\u0249\u024a\u0006\u0015\u000b\u0000\u024a;\u0001\u0000\u0000\u0000"+ - "\u024b\u024c\u0005/\u0000\u0000\u024c\u024d\u0005*\u0000\u0000\u024d\u0252"+ - "\u0001\u0000\u0000\u0000\u024e\u0251\u0003<\u0016\u0000\u024f\u0251\t"+ - "\u0000\u0000\u0000\u0250\u024e\u0001\u0000\u0000\u0000\u0250\u024f\u0001"+ - "\u0000\u0000\u0000\u0251\u0254\u0001\u0000\u0000\u0000\u0252\u0253\u0001"+ - "\u0000\u0000\u0000\u0252\u0250\u0001\u0000\u0000\u0000\u0253\u0255\u0001"+ - "\u0000\u0000\u0000\u0254\u0252\u0001\u0000\u0000\u0000\u0255\u0256\u0005"+ - "*\u0000\u0000\u0256\u0257\u0005/\u0000\u0000\u0257\u0258\u0001\u0000\u0000"+ - "\u0000\u0258\u0259\u0006\u0016\u000b\u0000\u0259=\u0001\u0000\u0000\u0000"+ - "\u025a\u025c\u0007\u0002\u0000\u0000\u025b\u025a\u0001\u0000\u0000\u0000"+ - "\u025c\u025d\u0001\u0000\u0000\u0000\u025d\u025b\u0001\u0000\u0000\u0000"+ - "\u025d\u025e\u0001\u0000\u0000\u0000\u025e\u025f\u0001\u0000\u0000\u0000"+ - "\u025f\u0260\u0006\u0017\u000b\u0000\u0260?\u0001\u0000\u0000\u0000\u0261"+ - "\u0265\b\u0003\u0000\u0000\u0262\u0263\u0005/\u0000\u0000\u0263\u0265"+ - "\b\u0004\u0000\u0000\u0264\u0261\u0001\u0000\u0000\u0000\u0264\u0262\u0001"+ - "\u0000\u0000\u0000\u0265A\u0001\u0000\u0000\u0000\u0266\u0268\u0003@\u0018"+ - "\u0000\u0267\u0266\u0001\u0000\u0000\u0000\u0268\u0269\u0001\u0000\u0000"+ - "\u0000\u0269\u0267\u0001\u0000\u0000\u0000\u0269\u026a\u0001\u0000\u0000"+ - "\u0000\u026aC\u0001\u0000\u0000\u0000\u026b\u026c\u0003\u00b0P\u0000\u026c"+ - "\u026d\u0001\u0000\u0000\u0000\u026d\u026e\u0006\u001a\f\u0000\u026e\u026f"+ - "\u0006\u001a\r\u0000\u026fE\u0001\u0000\u0000\u0000\u0270\u0271\u0003"+ - "N\u001f\u0000\u0271\u0272\u0001\u0000\u0000\u0000\u0272\u0273\u0006\u001b"+ - "\u000e\u0000\u0273\u0274\u0006\u001b\u000f\u0000\u0274G\u0001\u0000\u0000"+ - "\u0000\u0275\u0276\u0003>\u0017\u0000\u0276\u0277\u0001\u0000\u0000\u0000"+ - "\u0277\u0278\u0006\u001c\u000b\u0000\u0278I\u0001\u0000\u0000\u0000\u0279"+ - "\u027a\u0003:\u0015\u0000\u027a\u027b\u0001\u0000\u0000\u0000\u027b\u027c"+ - "\u0006\u001d\u000b\u0000\u027cK\u0001\u0000\u0000\u0000\u027d\u027e\u0003"+ - "<\u0016\u0000\u027e\u027f\u0001\u0000\u0000\u0000\u027f\u0280\u0006\u001e"+ - "\u000b\u0000\u0280M\u0001\u0000\u0000\u0000\u0281\u0282\u0005|\u0000\u0000"+ - "\u0282\u0283\u0001\u0000\u0000\u0000\u0283\u0284\u0006\u001f\u000f\u0000"+ - "\u0284O\u0001\u0000\u0000\u0000\u0285\u0286\u0007\u0005\u0000\u0000\u0286"+ - "Q\u0001\u0000\u0000\u0000\u0287\u0288\u0007\u0006\u0000\u0000\u0288S\u0001"+ - "\u0000\u0000\u0000\u0289\u028a\u0005\\\u0000\u0000\u028a\u028b\u0007\u0007"+ - "\u0000\u0000\u028bU\u0001\u0000\u0000\u0000\u028c\u028d\b\b\u0000\u0000"+ - "\u028dW\u0001\u0000\u0000\u0000\u028e\u0290\u0007\t\u0000\u0000\u028f"+ - "\u0291\u0007\n\u0000\u0000\u0290\u028f\u0001\u0000\u0000\u0000\u0290\u0291"+ - "\u0001\u0000\u0000\u0000\u0291\u0293\u0001\u0000\u0000\u0000\u0292\u0294"+ - "\u0003P \u0000\u0293\u0292\u0001\u0000\u0000\u0000\u0294\u0295\u0001\u0000"+ - "\u0000\u0000\u0295\u0293\u0001\u0000\u0000\u0000\u0295\u0296\u0001\u0000"+ - "\u0000\u0000\u0296Y\u0001\u0000\u0000\u0000\u0297\u0298\u0005@\u0000\u0000"+ - "\u0298[\u0001\u0000\u0000\u0000\u0299\u029a\u0005`\u0000\u0000\u029a]"+ - "\u0001\u0000\u0000\u0000\u029b\u029f\b\u000b\u0000\u0000\u029c\u029d\u0005"+ - "`\u0000\u0000\u029d\u029f\u0005`\u0000\u0000\u029e\u029b\u0001\u0000\u0000"+ - "\u0000\u029e\u029c\u0001\u0000\u0000\u0000\u029f_\u0001\u0000\u0000\u0000"+ - "\u02a0\u02a1\u0005_\u0000\u0000\u02a1a\u0001\u0000\u0000\u0000\u02a2\u02a6"+ - "\u0003R!\u0000\u02a3\u02a6\u0003P \u0000\u02a4\u02a6\u0003`(\u0000\u02a5"+ - "\u02a2\u0001\u0000\u0000\u0000\u02a5\u02a3\u0001\u0000\u0000\u0000\u02a5"+ - "\u02a4\u0001\u0000\u0000\u0000\u02a6c\u0001\u0000\u0000\u0000\u02a7\u02ac"+ - "\u0005\"\u0000\u0000\u02a8\u02ab\u0003T\"\u0000\u02a9\u02ab\u0003V#\u0000"+ - "\u02aa\u02a8\u0001\u0000\u0000\u0000\u02aa\u02a9\u0001\u0000\u0000\u0000"+ - "\u02ab\u02ae\u0001\u0000\u0000\u0000\u02ac\u02aa\u0001\u0000\u0000\u0000"+ - "\u02ac\u02ad\u0001\u0000\u0000\u0000\u02ad\u02af\u0001\u0000\u0000\u0000"+ - "\u02ae\u02ac\u0001\u0000\u0000\u0000\u02af\u02c5\u0005\"\u0000\u0000\u02b0"+ - "\u02b1\u0005\"\u0000\u0000\u02b1\u02b2\u0005\"\u0000\u0000\u02b2\u02b3"+ - "\u0005\"\u0000\u0000\u02b3\u02b7\u0001\u0000\u0000\u0000\u02b4\u02b6\b"+ - "\u0001\u0000\u0000\u02b5\u02b4\u0001\u0000\u0000\u0000\u02b6\u02b9\u0001"+ - "\u0000\u0000\u0000\u02b7\u02b8\u0001\u0000\u0000\u0000\u02b7\u02b5\u0001"+ - "\u0000\u0000\u0000\u02b8\u02ba\u0001\u0000\u0000\u0000\u02b9\u02b7\u0001"+ - "\u0000\u0000\u0000\u02ba\u02bb\u0005\"\u0000\u0000\u02bb\u02bc\u0005\""+ - "\u0000\u0000\u02bc\u02bd\u0005\"\u0000\u0000\u02bd\u02bf\u0001\u0000\u0000"+ - "\u0000\u02be\u02c0\u0005\"\u0000\u0000\u02bf\u02be\u0001\u0000\u0000\u0000"+ - "\u02bf\u02c0\u0001\u0000\u0000\u0000\u02c0\u02c2\u0001\u0000\u0000\u0000"+ - "\u02c1\u02c3\u0005\"\u0000\u0000\u02c2\u02c1\u0001\u0000\u0000\u0000\u02c2"+ - "\u02c3\u0001\u0000\u0000\u0000\u02c3\u02c5\u0001\u0000\u0000\u0000\u02c4"+ - "\u02a7\u0001\u0000\u0000\u0000\u02c4\u02b0\u0001\u0000\u0000\u0000\u02c5"+ - "e\u0001\u0000\u0000\u0000\u02c6\u02c8\u0003P \u0000\u02c7\u02c6\u0001"+ - "\u0000\u0000\u0000\u02c8\u02c9\u0001\u0000\u0000\u0000\u02c9\u02c7\u0001"+ - "\u0000\u0000\u0000\u02c9\u02ca\u0001\u0000\u0000\u0000\u02cag\u0001\u0000"+ - "\u0000\u0000\u02cb\u02cd\u0003P \u0000\u02cc\u02cb\u0001\u0000\u0000\u0000"+ - "\u02cd\u02ce\u0001\u0000\u0000\u0000\u02ce\u02cc\u0001\u0000\u0000\u0000"+ - "\u02ce\u02cf\u0001\u0000\u0000\u0000\u02cf\u02d0\u0001\u0000\u0000\u0000"+ - "\u02d0\u02d4\u0003x4\u0000\u02d1\u02d3\u0003P \u0000\u02d2\u02d1\u0001"+ - "\u0000\u0000\u0000\u02d3\u02d6\u0001\u0000\u0000\u0000\u02d4\u02d2\u0001"+ - "\u0000\u0000\u0000\u02d4\u02d5\u0001\u0000\u0000\u0000\u02d5\u02f6\u0001"+ - "\u0000\u0000\u0000\u02d6\u02d4\u0001\u0000\u0000\u0000\u02d7\u02d9\u0003"+ - "x4\u0000\u02d8\u02da\u0003P \u0000\u02d9\u02d8\u0001\u0000\u0000\u0000"+ - "\u02da\u02db\u0001\u0000\u0000\u0000\u02db\u02d9\u0001\u0000\u0000\u0000"+ - "\u02db\u02dc\u0001\u0000\u0000\u0000\u02dc\u02f6\u0001\u0000\u0000\u0000"+ - "\u02dd\u02df\u0003P \u0000\u02de\u02dd\u0001\u0000\u0000\u0000\u02df\u02e0"+ - "\u0001\u0000\u0000\u0000\u02e0\u02de\u0001\u0000\u0000\u0000\u02e0\u02e1"+ - "\u0001\u0000\u0000\u0000\u02e1\u02e9\u0001\u0000\u0000\u0000\u02e2\u02e6"+ - "\u0003x4\u0000\u02e3\u02e5\u0003P \u0000\u02e4\u02e3\u0001\u0000\u0000"+ - "\u0000\u02e5\u02e8\u0001\u0000\u0000\u0000\u02e6\u02e4\u0001\u0000\u0000"+ - "\u0000\u02e6\u02e7\u0001\u0000\u0000\u0000\u02e7\u02ea\u0001\u0000\u0000"+ - "\u0000\u02e8\u02e6\u0001\u0000\u0000\u0000\u02e9\u02e2\u0001\u0000\u0000"+ - "\u0000\u02e9\u02ea\u0001\u0000\u0000\u0000\u02ea\u02eb\u0001\u0000\u0000"+ - "\u0000\u02eb\u02ec\u0003X$\u0000\u02ec\u02f6\u0001\u0000\u0000\u0000\u02ed"+ - "\u02ef\u0003x4\u0000\u02ee\u02f0\u0003P \u0000\u02ef\u02ee\u0001\u0000"+ - "\u0000\u0000\u02f0\u02f1\u0001\u0000\u0000\u0000\u02f1\u02ef\u0001\u0000"+ - "\u0000\u0000\u02f1\u02f2\u0001\u0000\u0000\u0000\u02f2\u02f3\u0001\u0000"+ - "\u0000\u0000\u02f3\u02f4\u0003X$\u0000\u02f4\u02f6\u0001\u0000\u0000\u0000"+ - "\u02f5\u02cc\u0001\u0000\u0000\u0000\u02f5\u02d7\u0001\u0000\u0000\u0000"+ - "\u02f5\u02de\u0001\u0000\u0000\u0000\u02f5\u02ed\u0001\u0000\u0000\u0000"+ - "\u02f6i\u0001\u0000\u0000\u0000\u02f7\u02f8\u0005b\u0000\u0000\u02f8\u02f9"+ - "\u0005y\u0000\u0000\u02f9k\u0001\u0000\u0000\u0000\u02fa\u02fb\u0005a"+ - "\u0000\u0000\u02fb\u02fc\u0005n\u0000\u0000\u02fc\u02fd\u0005d\u0000\u0000"+ - "\u02fdm\u0001\u0000\u0000\u0000\u02fe\u02ff\u0005a\u0000\u0000\u02ff\u0300"+ - "\u0005s\u0000\u0000\u0300\u0301\u0005c\u0000\u0000\u0301o\u0001\u0000"+ - "\u0000\u0000\u0302\u0303\u0005=\u0000\u0000\u0303q\u0001\u0000\u0000\u0000"+ - "\u0304\u0305\u0005:\u0000\u0000\u0305\u0306\u0005:\u0000\u0000\u0306s"+ - "\u0001\u0000\u0000\u0000\u0307\u0308\u0005,\u0000\u0000\u0308u\u0001\u0000"+ - "\u0000\u0000\u0309\u030a\u0005d\u0000\u0000\u030a\u030b\u0005e\u0000\u0000"+ - "\u030b\u030c\u0005s\u0000\u0000\u030c\u030d\u0005c\u0000\u0000\u030dw"+ - "\u0001\u0000\u0000\u0000\u030e\u030f\u0005.\u0000\u0000\u030fy\u0001\u0000"+ - "\u0000\u0000\u0310\u0311\u0005f\u0000\u0000\u0311\u0312\u0005a\u0000\u0000"+ - "\u0312\u0313\u0005l\u0000\u0000\u0313\u0314\u0005s\u0000\u0000\u0314\u0315"+ - "\u0005e\u0000\u0000\u0315{\u0001\u0000\u0000\u0000\u0316\u0317\u0005f"+ - "\u0000\u0000\u0317\u0318\u0005i\u0000\u0000\u0318\u0319\u0005r\u0000\u0000"+ - "\u0319\u031a\u0005s\u0000\u0000\u031a\u031b\u0005t\u0000\u0000\u031b}"+ - "\u0001\u0000\u0000\u0000\u031c\u031d\u0005l\u0000\u0000\u031d\u031e\u0005"+ - "a\u0000\u0000\u031e\u031f\u0005s\u0000\u0000\u031f\u0320\u0005t\u0000"+ - "\u0000\u0320\u007f\u0001\u0000\u0000\u0000\u0321\u0322\u0005(\u0000\u0000"+ - "\u0322\u0081\u0001\u0000\u0000\u0000\u0323\u0324\u0005i\u0000\u0000\u0324"+ - "\u0325\u0005n\u0000\u0000\u0325\u0083\u0001\u0000\u0000\u0000\u0326\u0327"+ - "\u0005i\u0000\u0000\u0327\u0328\u0005s\u0000\u0000\u0328\u0085\u0001\u0000"+ - "\u0000\u0000\u0329\u032a\u0005l\u0000\u0000\u032a\u032b\u0005i\u0000\u0000"+ - "\u032b\u032c\u0005k\u0000\u0000\u032c\u032d\u0005e\u0000\u0000\u032d\u0087"+ - "\u0001\u0000\u0000\u0000\u032e\u032f\u0005n\u0000\u0000\u032f\u0330\u0005"+ - "o\u0000\u0000\u0330\u0331\u0005t\u0000\u0000\u0331\u0089\u0001\u0000\u0000"+ - "\u0000\u0332\u0333\u0005n\u0000\u0000\u0333\u0334\u0005u\u0000\u0000\u0334"+ - "\u0335\u0005l\u0000\u0000\u0335\u0336\u0005l\u0000\u0000\u0336\u008b\u0001"+ - "\u0000\u0000\u0000\u0337\u0338\u0005n\u0000\u0000\u0338\u0339\u0005u\u0000"+ - "\u0000\u0339\u033a\u0005l\u0000\u0000\u033a\u033b\u0005l\u0000\u0000\u033b"+ - "\u033c\u0005s\u0000\u0000\u033c\u008d\u0001\u0000\u0000\u0000\u033d\u033e"+ - "\u0005o\u0000\u0000\u033e\u033f\u0005r\u0000\u0000\u033f\u008f\u0001\u0000"+ - "\u0000\u0000\u0340\u0341\u0005?\u0000\u0000\u0341\u0091\u0001\u0000\u0000"+ - "\u0000\u0342\u0343\u0005r\u0000\u0000\u0343\u0344\u0005l\u0000\u0000\u0344"+ - "\u0345\u0005i\u0000\u0000\u0345\u0346\u0005k\u0000\u0000\u0346\u0347\u0005"+ - "e\u0000\u0000\u0347\u0093\u0001\u0000\u0000\u0000\u0348\u0349\u0005)\u0000"+ - "\u0000\u0349\u0095\u0001\u0000\u0000\u0000\u034a\u034b\u0005t\u0000\u0000"+ - "\u034b\u034c\u0005r\u0000\u0000\u034c\u034d\u0005u\u0000\u0000\u034d\u034e"+ - "\u0005e\u0000\u0000\u034e\u0097\u0001\u0000\u0000\u0000\u034f\u0350\u0005"+ - "=\u0000\u0000\u0350\u0351\u0005=\u0000\u0000\u0351\u0099\u0001\u0000\u0000"+ - "\u0000\u0352\u0353\u0005=\u0000\u0000\u0353\u0354\u0005~\u0000\u0000\u0354"+ - "\u009b\u0001\u0000\u0000\u0000\u0355\u0356\u0005!\u0000\u0000\u0356\u0357"+ - "\u0005=\u0000\u0000\u0357\u009d\u0001\u0000\u0000\u0000\u0358\u0359\u0005"+ - "<\u0000\u0000\u0359\u009f\u0001\u0000\u0000\u0000\u035a\u035b\u0005<\u0000"+ - "\u0000\u035b\u035c\u0005=\u0000\u0000\u035c\u00a1\u0001\u0000\u0000\u0000"+ - "\u035d\u035e\u0005>\u0000\u0000\u035e\u00a3\u0001\u0000\u0000\u0000\u035f"+ - "\u0360\u0005>\u0000\u0000\u0360\u0361\u0005=\u0000\u0000\u0361\u00a5\u0001"+ - "\u0000\u0000\u0000\u0362\u0363\u0005+\u0000\u0000\u0363\u00a7\u0001\u0000"+ - "\u0000\u0000\u0364\u0365\u0005-\u0000\u0000\u0365\u00a9\u0001\u0000\u0000"+ - "\u0000\u0366\u0367\u0005*\u0000\u0000\u0367\u00ab\u0001\u0000\u0000\u0000"+ - "\u0368\u0369\u0005/\u0000\u0000\u0369\u00ad\u0001\u0000\u0000\u0000\u036a"+ - "\u036b\u0005%\u0000\u0000\u036b\u00af\u0001\u0000\u0000\u0000\u036c\u036d"+ - "\u0005[\u0000\u0000\u036d\u036e\u0001\u0000\u0000\u0000\u036e\u036f\u0006"+ - "P\u0000\u0000\u036f\u0370\u0006P\u0000\u0000\u0370\u00b1\u0001\u0000\u0000"+ - "\u0000\u0371\u0372\u0005]\u0000\u0000\u0372\u0373\u0001\u0000\u0000\u0000"+ - "\u0373\u0374\u0006Q\u000f\u0000\u0374\u0375\u0006Q\u000f\u0000\u0375\u00b3"+ - "\u0001\u0000\u0000\u0000\u0376\u037a\u0003R!\u0000\u0377\u0379\u0003b"+ - ")\u0000\u0378\u0377\u0001\u0000\u0000\u0000\u0379\u037c\u0001\u0000\u0000"+ - "\u0000\u037a\u0378\u0001\u0000\u0000\u0000\u037a\u037b\u0001\u0000\u0000"+ - "\u0000\u037b\u0387\u0001\u0000\u0000\u0000\u037c\u037a\u0001\u0000\u0000"+ - "\u0000\u037d\u0380\u0003`(\u0000\u037e\u0380\u0003Z%\u0000\u037f\u037d"+ - "\u0001\u0000\u0000\u0000\u037f\u037e\u0001\u0000\u0000\u0000\u0380\u0382"+ - "\u0001\u0000\u0000\u0000\u0381\u0383\u0003b)\u0000\u0382\u0381\u0001\u0000"+ - "\u0000\u0000\u0383\u0384\u0001\u0000\u0000\u0000\u0384\u0382\u0001\u0000"+ - "\u0000\u0000\u0384\u0385\u0001\u0000\u0000\u0000\u0385\u0387\u0001\u0000"+ - "\u0000\u0000\u0386\u0376\u0001\u0000\u0000\u0000\u0386\u037f\u0001\u0000"+ - "\u0000\u0000\u0387\u00b5\u0001\u0000\u0000\u0000\u0388\u038a\u0003\\&"+ - "\u0000\u0389\u038b\u0003^\'\u0000\u038a\u0389\u0001\u0000\u0000\u0000"+ - "\u038b\u038c\u0001\u0000\u0000\u0000\u038c\u038a\u0001\u0000\u0000\u0000"+ - "\u038c\u038d\u0001\u0000\u0000\u0000\u038d\u038e\u0001\u0000\u0000\u0000"+ - "\u038e\u038f\u0003\\&\u0000\u038f\u00b7\u0001\u0000\u0000\u0000\u0390"+ - "\u0391\u0003\u00b6S\u0000\u0391\u00b9\u0001\u0000\u0000\u0000\u0392\u0393"+ - "\u0003:\u0015\u0000\u0393\u0394\u0001\u0000\u0000\u0000\u0394\u0395\u0006"+ - "U\u000b\u0000\u0395\u00bb\u0001\u0000\u0000\u0000\u0396\u0397\u0003<\u0016"+ - "\u0000\u0397\u0398\u0001\u0000\u0000\u0000\u0398\u0399\u0006V\u000b\u0000"+ - "\u0399\u00bd\u0001\u0000\u0000\u0000\u039a\u039b\u0003>\u0017\u0000\u039b"+ - "\u039c\u0001\u0000\u0000\u0000\u039c\u039d\u0006W\u000b\u0000\u039d\u00bf"+ - "\u0001\u0000\u0000\u0000\u039e\u039f\u0003N\u001f\u0000\u039f\u03a0\u0001"+ - "\u0000\u0000\u0000\u03a0\u03a1\u0006X\u000e\u0000\u03a1\u03a2\u0006X\u000f"+ - "\u0000\u03a2\u00c1\u0001\u0000\u0000\u0000\u03a3\u03a4\u0003\u00b0P\u0000"+ - "\u03a4\u03a5\u0001\u0000\u0000\u0000\u03a5\u03a6\u0006Y\f\u0000\u03a6"+ - "\u00c3\u0001\u0000\u0000\u0000\u03a7\u03a8\u0003\u00b2Q\u0000\u03a8\u03a9"+ - "\u0001\u0000\u0000\u0000\u03a9\u03aa\u0006Z\u0010\u0000\u03aa\u00c5\u0001"+ - "\u0000\u0000\u0000\u03ab\u03ac\u0003t2\u0000\u03ac\u03ad\u0001\u0000\u0000"+ - "\u0000\u03ad\u03ae\u0006[\u0011\u0000\u03ae\u00c7\u0001\u0000\u0000\u0000"+ - "\u03af\u03b0\u0003p0\u0000\u03b0\u03b1\u0001\u0000\u0000\u0000\u03b1\u03b2"+ - "\u0006\\\u0012\u0000\u03b2\u00c9\u0001\u0000\u0000\u0000\u03b3\u03b4\u0003"+ - "d*\u0000\u03b4\u03b5\u0001\u0000\u0000\u0000\u03b5\u03b6\u0006]\u0013"+ - "\u0000\u03b6\u00cb\u0001\u0000\u0000\u0000\u03b7\u03b8\u0005m\u0000\u0000"+ - "\u03b8\u03b9\u0005e\u0000\u0000\u03b9\u03ba\u0005t\u0000\u0000\u03ba\u03bb"+ - "\u0005a\u0000\u0000\u03bb\u03bc\u0005d\u0000\u0000\u03bc\u03bd\u0005a"+ - "\u0000\u0000\u03bd\u03be\u0005t\u0000\u0000\u03be\u03bf\u0005a\u0000\u0000"+ - "\u03bf\u00cd\u0001\u0000\u0000\u0000\u03c0\u03c1\u0003B\u0019\u0000\u03c1"+ - "\u03c2\u0001\u0000\u0000\u0000\u03c2\u03c3\u0006_\u0014\u0000\u03c3\u00cf"+ - "\u0001\u0000\u0000\u0000\u03c4\u03c5\u0003:\u0015\u0000\u03c5\u03c6\u0001"+ - "\u0000\u0000\u0000\u03c6\u03c7\u0006`\u000b\u0000\u03c7\u00d1\u0001\u0000"+ - "\u0000\u0000\u03c8\u03c9\u0003<\u0016\u0000\u03c9\u03ca\u0001\u0000\u0000"+ - "\u0000\u03ca\u03cb\u0006a\u000b\u0000\u03cb\u00d3\u0001\u0000\u0000\u0000"+ - "\u03cc\u03cd\u0003>\u0017\u0000\u03cd\u03ce\u0001\u0000\u0000\u0000\u03ce"+ - "\u03cf\u0006b\u000b\u0000\u03cf\u00d5\u0001\u0000\u0000\u0000\u03d0\u03d1"+ - "\u0003N\u001f\u0000\u03d1\u03d2\u0001\u0000\u0000\u0000\u03d2\u03d3\u0006"+ - "c\u000e\u0000\u03d3\u03d4\u0006c\u000f\u0000\u03d4\u00d7\u0001\u0000\u0000"+ - "\u0000\u03d5\u03d6\u0003x4\u0000\u03d6\u03d7\u0001\u0000\u0000\u0000\u03d7"+ - "\u03d8\u0006d\u0015\u0000\u03d8\u00d9\u0001\u0000\u0000\u0000\u03d9\u03da"+ - "\u0003t2\u0000\u03da\u03db\u0001\u0000\u0000\u0000\u03db\u03dc\u0006e"+ - "\u0011\u0000\u03dc\u00db\u0001\u0000\u0000\u0000\u03dd\u03e2\u0003R!\u0000"+ - "\u03de\u03e2\u0003P \u0000\u03df\u03e2\u0003`(\u0000\u03e0\u03e2\u0003"+ - "\u00aaM\u0000\u03e1\u03dd\u0001\u0000\u0000\u0000\u03e1\u03de\u0001\u0000"+ - "\u0000\u0000\u03e1\u03df\u0001\u0000\u0000\u0000\u03e1\u03e0\u0001\u0000"+ - "\u0000\u0000\u03e2\u00dd\u0001\u0000\u0000\u0000\u03e3\u03e6\u0003R!\u0000"+ - "\u03e4\u03e6\u0003\u00aaM\u0000\u03e5\u03e3\u0001\u0000\u0000\u0000\u03e5"+ - "\u03e4\u0001\u0000\u0000\u0000\u03e6\u03ea\u0001\u0000\u0000\u0000\u03e7"+ - "\u03e9\u0003\u00dcf\u0000\u03e8\u03e7\u0001\u0000\u0000\u0000\u03e9\u03ec"+ - "\u0001\u0000\u0000\u0000\u03ea\u03e8\u0001\u0000\u0000\u0000\u03ea\u03eb"+ - "\u0001\u0000\u0000\u0000\u03eb\u03f7\u0001\u0000\u0000\u0000\u03ec\u03ea"+ - "\u0001\u0000\u0000\u0000\u03ed\u03f0\u0003`(\u0000\u03ee\u03f0\u0003Z"+ - "%\u0000\u03ef\u03ed\u0001\u0000\u0000\u0000\u03ef\u03ee\u0001\u0000\u0000"+ - "\u0000\u03f0\u03f2\u0001\u0000\u0000\u0000\u03f1\u03f3\u0003\u00dcf\u0000"+ - "\u03f2\u03f1\u0001\u0000\u0000\u0000\u03f3\u03f4\u0001\u0000\u0000\u0000"+ - "\u03f4\u03f2\u0001\u0000\u0000\u0000\u03f4\u03f5\u0001\u0000\u0000\u0000"+ - "\u03f5\u03f7\u0001\u0000\u0000\u0000\u03f6\u03e5\u0001\u0000\u0000\u0000"+ - "\u03f6\u03ef\u0001\u0000\u0000\u0000\u03f7\u00df\u0001\u0000\u0000\u0000"+ - "\u03f8\u03fb\u0003\u00deg\u0000\u03f9\u03fb\u0003\u00b6S\u0000\u03fa\u03f8"+ - "\u0001\u0000\u0000\u0000\u03fa\u03f9\u0001\u0000\u0000\u0000\u03fb\u03fc"+ - "\u0001\u0000\u0000\u0000\u03fc\u03fa\u0001\u0000\u0000\u0000\u03fc\u03fd"+ - "\u0001\u0000\u0000\u0000\u03fd\u00e1\u0001\u0000\u0000\u0000\u03fe\u03ff"+ - "\u0003:\u0015\u0000\u03ff\u0400\u0001\u0000\u0000\u0000\u0400\u0401\u0006"+ - "i\u000b\u0000\u0401\u00e3\u0001\u0000\u0000\u0000\u0402\u0403\u0003<\u0016"+ - "\u0000\u0403\u0404\u0001\u0000\u0000\u0000\u0404\u0405\u0006j\u000b\u0000"+ - "\u0405\u00e5\u0001\u0000\u0000\u0000\u0406\u0407\u0003>\u0017\u0000\u0407"+ - "\u0408\u0001\u0000\u0000\u0000\u0408\u0409\u0006k\u000b\u0000\u0409\u00e7"+ - "\u0001\u0000\u0000\u0000\u040a\u040b\u0003N\u001f\u0000\u040b\u040c\u0001"+ - "\u0000\u0000\u0000\u040c\u040d\u0006l\u000e\u0000\u040d\u040e\u0006l\u000f"+ - "\u0000\u040e\u00e9\u0001\u0000\u0000\u0000\u040f\u0410\u0003p0\u0000\u0410"+ - "\u0411\u0001\u0000\u0000\u0000\u0411\u0412\u0006m\u0012\u0000\u0412\u00eb"+ - "\u0001\u0000\u0000\u0000\u0413\u0414\u0003t2\u0000\u0414\u0415\u0001\u0000"+ - "\u0000\u0000\u0415\u0416\u0006n\u0011\u0000\u0416\u00ed\u0001\u0000\u0000"+ - "\u0000\u0417\u0418\u0003x4\u0000\u0418\u0419\u0001\u0000\u0000\u0000\u0419"+ - "\u041a\u0006o\u0015\u0000\u041a\u00ef\u0001\u0000\u0000\u0000\u041b\u041c"+ - "\u0005a\u0000\u0000\u041c\u041d\u0005s\u0000\u0000\u041d\u00f1\u0001\u0000"+ - "\u0000\u0000\u041e\u041f\u0003\u00e0h\u0000\u041f\u0420\u0001\u0000\u0000"+ - "\u0000\u0420\u0421\u0006q\u0016\u0000\u0421\u00f3\u0001\u0000\u0000\u0000"+ - "\u0422\u0423\u0003:\u0015\u0000\u0423\u0424\u0001\u0000\u0000\u0000\u0424"+ - "\u0425\u0006r\u000b\u0000\u0425\u00f5\u0001\u0000\u0000\u0000\u0426\u0427"+ - "\u0003<\u0016\u0000\u0427\u0428\u0001\u0000\u0000\u0000\u0428\u0429\u0006"+ - "s\u000b\u0000\u0429\u00f7\u0001\u0000\u0000\u0000\u042a\u042b\u0003>\u0017"+ - "\u0000\u042b\u042c\u0001\u0000\u0000\u0000\u042c\u042d\u0006t\u000b\u0000"+ - "\u042d\u00f9\u0001\u0000\u0000\u0000\u042e\u042f\u0003N\u001f\u0000\u042f"+ - "\u0430\u0001\u0000\u0000\u0000\u0430\u0431\u0006u\u000e\u0000\u0431\u0432"+ - "\u0006u\u000f\u0000\u0432\u00fb\u0001\u0000\u0000\u0000\u0433\u0434\u0003"+ - "\u00b0P\u0000\u0434\u0435\u0001\u0000\u0000\u0000\u0435\u0436\u0006v\f"+ - "\u0000\u0436\u0437\u0006v\u0017\u0000\u0437\u00fd\u0001\u0000\u0000\u0000"+ - "\u0438\u0439\u0005o\u0000\u0000\u0439\u043a\u0005n\u0000\u0000\u043a\u043b"+ - "\u0001\u0000\u0000\u0000\u043b\u043c\u0006w\u0018\u0000\u043c\u00ff\u0001"+ - "\u0000\u0000\u0000\u043d\u043e\u0005w\u0000\u0000\u043e\u043f\u0005i\u0000"+ - "\u0000\u043f\u0440\u0005t\u0000\u0000\u0440\u0441\u0005h\u0000\u0000\u0441"+ - "\u0442\u0001\u0000\u0000\u0000\u0442\u0443\u0006x\u0018\u0000\u0443\u0101"+ - "\u0001\u0000\u0000\u0000\u0444\u0445\b\f\u0000\u0000\u0445\u0103\u0001"+ - "\u0000\u0000\u0000\u0446\u0448\u0003\u0102y\u0000\u0447\u0446\u0001\u0000"+ - "\u0000\u0000\u0448\u0449\u0001\u0000\u0000\u0000\u0449\u0447\u0001\u0000"+ - "\u0000\u0000\u0449\u044a\u0001\u0000\u0000\u0000\u044a\u044b\u0001\u0000"+ - "\u0000\u0000\u044b\u044c\u0003\u0166\u00ab\u0000\u044c\u044e\u0001\u0000"+ - "\u0000\u0000\u044d\u0447\u0001\u0000\u0000\u0000\u044d\u044e\u0001\u0000"+ - "\u0000\u0000\u044e\u0450\u0001\u0000\u0000\u0000\u044f\u0451\u0003\u0102"+ - "y\u0000\u0450\u044f\u0001\u0000\u0000\u0000\u0451\u0452\u0001\u0000\u0000"+ - "\u0000\u0452\u0450\u0001\u0000\u0000\u0000\u0452\u0453\u0001\u0000\u0000"+ - "\u0000\u0453\u0105\u0001\u0000\u0000\u0000\u0454\u0455\u0003\u00b8T\u0000"+ - "\u0455\u0456\u0001\u0000\u0000\u0000\u0456\u0457\u0006{\u0019\u0000\u0457"+ - "\u0107\u0001\u0000\u0000\u0000\u0458\u0459\u0003\u0104z\u0000\u0459\u045a"+ - "\u0001\u0000\u0000\u0000\u045a\u045b\u0006|\u001a\u0000\u045b\u0109\u0001"+ - "\u0000\u0000\u0000\u045c\u045d\u0003:\u0015\u0000\u045d\u045e\u0001\u0000"+ - "\u0000\u0000\u045e\u045f\u0006}\u000b\u0000\u045f\u010b\u0001\u0000\u0000"+ - "\u0000\u0460\u0461\u0003<\u0016\u0000\u0461\u0462\u0001\u0000\u0000\u0000"+ - "\u0462\u0463\u0006~\u000b\u0000\u0463\u010d\u0001\u0000\u0000\u0000\u0464"+ - "\u0465\u0003>\u0017\u0000\u0465\u0466\u0001\u0000\u0000\u0000\u0466\u0467"+ - "\u0006\u007f\u000b\u0000\u0467\u010f\u0001\u0000\u0000\u0000\u0468\u0469"+ - "\u0003N\u001f\u0000\u0469\u046a\u0001\u0000\u0000\u0000\u046a\u046b\u0006"+ - "\u0080\u000e\u0000\u046b\u046c\u0006\u0080\u000f\u0000\u046c\u046d\u0006"+ - "\u0080\u000f\u0000\u046d\u0111\u0001\u0000\u0000\u0000\u046e\u046f\u0003"+ - "p0\u0000\u046f\u0470\u0001\u0000\u0000\u0000\u0470\u0471\u0006\u0081\u0012"+ - "\u0000\u0471\u0113\u0001\u0000\u0000\u0000\u0472\u0473\u0003t2\u0000\u0473"+ - "\u0474\u0001\u0000\u0000\u0000\u0474\u0475\u0006\u0082\u0011\u0000\u0475"+ - "\u0115\u0001\u0000\u0000\u0000\u0476\u0477\u0003x4\u0000\u0477\u0478\u0001"+ - "\u0000\u0000\u0000\u0478\u0479\u0006\u0083\u0015\u0000\u0479\u0117\u0001"+ - "\u0000\u0000\u0000\u047a\u047b\u0003\u0100x\u0000\u047b\u047c\u0001\u0000"+ - "\u0000\u0000\u047c\u047d\u0006\u0084\u001b\u0000\u047d\u0119\u0001\u0000"+ - "\u0000\u0000\u047e\u047f\u0003\u00e0h\u0000\u047f\u0480\u0001\u0000\u0000"+ - "\u0000\u0480\u0481\u0006\u0085\u0016\u0000\u0481\u011b\u0001\u0000\u0000"+ - "\u0000\u0482\u0483\u0003\u00b8T\u0000\u0483\u0484\u0001\u0000\u0000\u0000"+ - "\u0484\u0485\u0006\u0086\u0019\u0000\u0485\u011d\u0001\u0000\u0000\u0000"+ - "\u0486\u0487\u0003:\u0015\u0000\u0487\u0488\u0001\u0000\u0000\u0000\u0488"+ - "\u0489\u0006\u0087\u000b\u0000\u0489\u011f\u0001\u0000\u0000\u0000\u048a"+ - "\u048b\u0003<\u0016\u0000\u048b\u048c\u0001\u0000\u0000\u0000\u048c\u048d"+ - "\u0006\u0088\u000b\u0000\u048d\u0121\u0001\u0000\u0000\u0000\u048e\u048f"+ - "\u0003>\u0017\u0000\u048f\u0490\u0001\u0000\u0000\u0000\u0490\u0491\u0006"+ - "\u0089\u000b\u0000\u0491\u0123\u0001\u0000\u0000\u0000\u0492\u0493\u0003"+ - "N\u001f\u0000\u0493\u0494\u0001\u0000\u0000\u0000\u0494\u0495\u0006\u008a"+ - "\u000e\u0000\u0495\u0496\u0006\u008a\u000f\u0000\u0496\u0125\u0001\u0000"+ - "\u0000\u0000\u0497\u0498\u0003t2\u0000\u0498\u0499\u0001\u0000\u0000\u0000"+ - "\u0499\u049a\u0006\u008b\u0011\u0000\u049a\u0127\u0001\u0000\u0000\u0000"+ - "\u049b\u049c\u0003x4\u0000\u049c\u049d\u0001\u0000\u0000\u0000\u049d\u049e"+ - "\u0006\u008c\u0015\u0000\u049e\u0129\u0001\u0000\u0000\u0000\u049f\u04a0"+ - "\u0003\u00few\u0000\u04a0\u04a1\u0001\u0000\u0000\u0000\u04a1\u04a2\u0006"+ - "\u008d\u001c\u0000\u04a2\u04a3\u0006\u008d\u001d\u0000\u04a3\u012b\u0001"+ - "\u0000\u0000\u0000\u04a4\u04a5\u0003B\u0019\u0000\u04a5\u04a6\u0001\u0000"+ - "\u0000\u0000\u04a6\u04a7\u0006\u008e\u0014\u0000\u04a7\u012d\u0001\u0000"+ - "\u0000\u0000\u04a8\u04a9\u0003:\u0015\u0000\u04a9\u04aa\u0001\u0000\u0000"+ - "\u0000\u04aa\u04ab\u0006\u008f\u000b\u0000\u04ab\u012f\u0001\u0000\u0000"+ - "\u0000\u04ac\u04ad\u0003<\u0016\u0000\u04ad\u04ae\u0001\u0000\u0000\u0000"+ - "\u04ae\u04af\u0006\u0090\u000b\u0000\u04af\u0131\u0001\u0000\u0000\u0000"+ - "\u04b0\u04b1\u0003>\u0017\u0000\u04b1\u04b2\u0001\u0000\u0000\u0000\u04b2"+ - "\u04b3\u0006\u0091\u000b\u0000\u04b3\u0133\u0001\u0000\u0000\u0000\u04b4"+ - "\u04b5\u0003N\u001f\u0000\u04b5\u04b6\u0001\u0000\u0000\u0000\u04b6\u04b7"+ - "\u0006\u0092\u000e\u0000\u04b7\u04b8\u0006\u0092\u000f\u0000\u04b8\u04b9"+ - "\u0006\u0092\u000f\u0000\u04b9\u0135\u0001\u0000\u0000\u0000\u04ba\u04bb"+ - "\u0003t2\u0000\u04bb\u04bc\u0001\u0000\u0000\u0000\u04bc\u04bd\u0006\u0093"+ - "\u0011\u0000\u04bd\u0137\u0001\u0000\u0000\u0000\u04be\u04bf\u0003x4\u0000"+ - "\u04bf\u04c0\u0001\u0000\u0000\u0000\u04c0\u04c1\u0006\u0094\u0015\u0000"+ - "\u04c1\u0139\u0001\u0000\u0000\u0000\u04c2\u04c3\u0003\u00e0h\u0000\u04c3"+ - "\u04c4\u0001\u0000\u0000\u0000\u04c4\u04c5\u0006\u0095\u0016\u0000\u04c5"+ - "\u013b\u0001\u0000\u0000\u0000\u04c6\u04c7\u0003:\u0015\u0000\u04c7\u04c8"+ - "\u0001\u0000\u0000\u0000\u04c8\u04c9\u0006\u0096\u000b\u0000\u04c9\u013d"+ - "\u0001\u0000\u0000\u0000\u04ca\u04cb\u0003<\u0016\u0000\u04cb\u04cc\u0001"+ - "\u0000\u0000\u0000\u04cc\u04cd\u0006\u0097\u000b\u0000\u04cd\u013f\u0001"+ - "\u0000\u0000\u0000\u04ce\u04cf\u0003>\u0017\u0000\u04cf\u04d0\u0001\u0000"+ - "\u0000\u0000\u04d0\u04d1\u0006\u0098\u000b\u0000\u04d1\u0141\u0001\u0000"+ - "\u0000\u0000\u04d2\u04d3\u0003N\u001f\u0000\u04d3\u04d4\u0001\u0000\u0000"+ - "\u0000\u04d4\u04d5\u0006\u0099\u000e\u0000\u04d5\u04d6\u0006\u0099\u000f"+ - "\u0000\u04d6\u0143\u0001\u0000\u0000\u0000\u04d7\u04d8\u0003x4\u0000\u04d8"+ - "\u04d9\u0001\u0000\u0000\u0000\u04d9\u04da\u0006\u009a\u0015\u0000\u04da"+ - "\u0145\u0001\u0000\u0000\u0000\u04db\u04dc\u0003\u00b8T\u0000\u04dc\u04dd"+ - "\u0001\u0000\u0000\u0000\u04dd\u04de\u0006\u009b\u0019\u0000\u04de\u0147"+ - "\u0001\u0000\u0000\u0000\u04df\u04e0\u0003\u00b4R\u0000\u04e0\u04e1\u0001"+ - "\u0000\u0000\u0000\u04e1\u04e2\u0006\u009c\u001e\u0000\u04e2\u0149\u0001"+ - "\u0000\u0000\u0000\u04e3\u04e4\u0003:\u0015\u0000\u04e4\u04e5\u0001\u0000"+ - "\u0000\u0000\u04e5\u04e6\u0006\u009d\u000b\u0000\u04e6\u014b\u0001\u0000"+ - "\u0000\u0000\u04e7\u04e8\u0003<\u0016\u0000\u04e8\u04e9\u0001\u0000\u0000"+ - "\u0000\u04e9\u04ea\u0006\u009e\u000b\u0000\u04ea\u014d\u0001\u0000\u0000"+ - "\u0000\u04eb\u04ec\u0003>\u0017\u0000\u04ec\u04ed\u0001\u0000\u0000\u0000"+ - "\u04ed\u04ee\u0006\u009f\u000b\u0000\u04ee\u014f\u0001\u0000\u0000\u0000"+ - "\u04ef\u04f0\u0003N\u001f\u0000\u04f0\u04f1\u0001\u0000\u0000\u0000\u04f1"+ - "\u04f2\u0006\u00a0\u000e\u0000\u04f2\u04f3\u0006\u00a0\u000f\u0000\u04f3"+ - "\u0151\u0001\u0000\u0000\u0000\u04f4\u04f5\u0005i\u0000\u0000\u04f5\u04f6"+ - "\u0005n\u0000\u0000\u04f6\u04f7\u0005f\u0000\u0000\u04f7\u04f8\u0005o"+ - "\u0000\u0000\u04f8\u0153\u0001\u0000\u0000\u0000\u04f9\u04fa\u0003:\u0015"+ - "\u0000\u04fa\u04fb\u0001\u0000\u0000\u0000\u04fb\u04fc\u0006\u00a2\u000b"+ - "\u0000\u04fc\u0155\u0001\u0000\u0000\u0000\u04fd\u04fe\u0003<\u0016\u0000"+ - "\u04fe\u04ff\u0001\u0000\u0000\u0000\u04ff\u0500\u0006\u00a3\u000b\u0000"+ - "\u0500\u0157\u0001\u0000\u0000\u0000\u0501\u0502\u0003>\u0017\u0000\u0502"+ - "\u0503\u0001\u0000\u0000\u0000\u0503\u0504\u0006\u00a4\u000b\u0000\u0504"+ - "\u0159\u0001\u0000\u0000\u0000\u0505\u0506\u0003N\u001f\u0000\u0506\u0507"+ - "\u0001\u0000\u0000\u0000\u0507\u0508\u0006\u00a5\u000e\u0000\u0508\u0509"+ - "\u0006\u00a5\u000f\u0000\u0509\u015b\u0001\u0000\u0000\u0000\u050a\u050b"+ - "\u0005f\u0000\u0000\u050b\u050c\u0005u\u0000\u0000\u050c\u050d\u0005n"+ - "\u0000\u0000\u050d\u050e\u0005c\u0000\u0000\u050e\u050f\u0005t\u0000\u0000"+ - "\u050f\u0510\u0005i\u0000\u0000\u0510\u0511\u0005o\u0000\u0000\u0511\u0512"+ - "\u0005n\u0000\u0000\u0512\u0513\u0005s\u0000\u0000\u0513\u015d\u0001\u0000"+ - "\u0000\u0000\u0514\u0515\u0003:\u0015\u0000\u0515\u0516\u0001\u0000\u0000"+ - "\u0000\u0516\u0517\u0006\u00a7\u000b\u0000\u0517\u015f\u0001\u0000\u0000"+ - "\u0000\u0518\u0519\u0003<\u0016\u0000\u0519\u051a\u0001\u0000\u0000\u0000"+ - "\u051a\u051b\u0006\u00a8\u000b\u0000\u051b\u0161\u0001\u0000\u0000\u0000"+ - "\u051c\u051d\u0003>\u0017\u0000\u051d\u051e\u0001\u0000\u0000\u0000\u051e"+ - "\u051f\u0006\u00a9\u000b\u0000\u051f\u0163\u0001\u0000\u0000\u0000\u0520"+ - "\u0521\u0003\u00b2Q\u0000\u0521\u0522\u0001\u0000\u0000\u0000\u0522\u0523"+ - "\u0006\u00aa\u0010\u0000\u0523\u0524\u0006\u00aa\u000f\u0000\u0524\u0165"+ - "\u0001\u0000\u0000\u0000\u0525\u0526\u0005:\u0000\u0000\u0526\u0167\u0001"+ - "\u0000\u0000\u0000\u0527\u052d\u0003Z%\u0000\u0528\u052d\u0003P \u0000"+ - "\u0529\u052d\u0003x4\u0000\u052a\u052d\u0003R!\u0000\u052b\u052d\u0003"+ - "`(\u0000\u052c\u0527\u0001\u0000\u0000\u0000\u052c\u0528\u0001\u0000\u0000"+ - "\u0000\u052c\u0529\u0001\u0000\u0000\u0000\u052c\u052a\u0001\u0000\u0000"+ - "\u0000\u052c\u052b\u0001\u0000\u0000\u0000\u052d\u052e\u0001\u0000\u0000"+ - "\u0000\u052e\u052c\u0001\u0000\u0000\u0000\u052e\u052f\u0001\u0000\u0000"+ - "\u0000\u052f\u0169\u0001\u0000\u0000\u0000\u0530\u0531\u0003:\u0015\u0000"+ - "\u0531\u0532\u0001\u0000\u0000\u0000\u0532\u0533\u0006\u00ad\u000b\u0000"+ - "\u0533\u016b\u0001\u0000\u0000\u0000\u0534\u0535\u0003<\u0016\u0000\u0535"+ - "\u0536\u0001\u0000\u0000\u0000\u0536\u0537\u0006\u00ae\u000b\u0000\u0537"+ - "\u016d\u0001\u0000\u0000\u0000\u0538\u0539\u0003>\u0017\u0000\u0539\u053a"+ - "\u0001\u0000\u0000\u0000\u053a\u053b\u0006\u00af\u000b\u0000\u053b\u016f"+ - "\u0001\u0000\u0000\u0000\u053c\u053d\u0003N\u001f\u0000\u053d\u053e\u0001"+ - "\u0000\u0000\u0000\u053e\u053f\u0006\u00b0\u000e\u0000\u053f\u0540\u0006"+ - "\u00b0\u000f\u0000\u0540\u0171\u0001\u0000\u0000\u0000\u0541\u0542\u0003"+ - "B\u0019\u0000\u0542\u0543\u0001\u0000\u0000\u0000\u0543\u0544\u0006\u00b1"+ - "\u0014\u0000\u0544\u0545\u0006\u00b1\u000f\u0000\u0545\u0546\u0006\u00b1"+ - "\u001f\u0000\u0546\u0173\u0001\u0000\u0000\u0000\u0547\u0548\u0003:\u0015"+ - "\u0000\u0548\u0549\u0001\u0000\u0000\u0000\u0549\u054a\u0006\u00b2\u000b"+ - "\u0000\u054a\u0175\u0001\u0000\u0000\u0000\u054b\u054c\u0003<\u0016\u0000"+ - "\u054c\u054d\u0001\u0000\u0000\u0000\u054d\u054e\u0006\u00b3\u000b\u0000"+ - "\u054e\u0177\u0001\u0000\u0000\u0000\u054f\u0550\u0003>\u0017\u0000\u0550"+ - "\u0551\u0001\u0000\u0000\u0000\u0551\u0552\u0006\u00b4\u000b\u0000\u0552"+ - "\u0179\u0001\u0000\u0000\u0000\u0553\u0554\u0003t2\u0000\u0554\u0555\u0001"+ - "\u0000\u0000\u0000\u0555\u0556\u0006\u00b5\u0011\u0000\u0556\u0557\u0006"+ - "\u00b5\u000f\u0000\u0557\u0558\u0006\u00b5\u0007\u0000\u0558\u017b\u0001"+ - "\u0000\u0000\u0000\u0559\u055a\u0003:\u0015\u0000\u055a\u055b\u0001\u0000"+ - "\u0000\u0000\u055b\u055c\u0006\u00b6\u000b\u0000\u055c\u017d\u0001\u0000"+ - "\u0000\u0000\u055d\u055e\u0003<\u0016\u0000\u055e\u055f\u0001\u0000\u0000"+ - "\u0000\u055f\u0560\u0006\u00b7\u000b\u0000\u0560\u017f\u0001\u0000\u0000"+ - "\u0000\u0561\u0562\u0003>\u0017\u0000\u0562\u0563\u0001\u0000\u0000\u0000"+ - "\u0563\u0564\u0006\u00b8\u000b\u0000\u0564\u0181\u0001\u0000\u0000\u0000"+ - "\u0565\u0566\u0003\u00b8T\u0000\u0566\u0567\u0001\u0000\u0000\u0000\u0567"+ - "\u0568\u0006\u00b9\u000f\u0000\u0568\u0569\u0006\u00b9\u0000\u0000\u0569"+ - "\u056a\u0006\u00b9\u0019\u0000\u056a\u0183\u0001\u0000\u0000\u0000\u056b"+ - "\u056c\u0003\u00b4R\u0000\u056c\u056d\u0001\u0000\u0000\u0000\u056d\u056e"+ - "\u0006\u00ba\u000f\u0000\u056e\u056f\u0006\u00ba\u0000\u0000\u056f\u0570"+ - "\u0006\u00ba\u001e\u0000\u0570\u0185\u0001\u0000\u0000\u0000\u0571\u0572"+ - "\u0003j-\u0000\u0572\u0573\u0001\u0000\u0000\u0000\u0573\u0574\u0006\u00bb"+ - "\u000f\u0000\u0574\u0575\u0006\u00bb\u0000\u0000\u0575\u0576\u0006\u00bb"+ - " \u0000\u0576\u0187\u0001\u0000\u0000\u0000\u0577\u0578\u0003N\u001f\u0000"+ - "\u0578\u0579\u0001\u0000\u0000\u0000\u0579\u057a\u0006\u00bc\u000e\u0000"+ - "\u057a\u057b\u0006\u00bc\u000f\u0000\u057b\u0189\u0001\u0000\u0000\u0000"+ - ">\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e"+ - "\u000f\u0236\u0240\u0244\u0247\u0250\u0252\u025d\u0264\u0269\u0290\u0295"+ - "\u029e\u02a5\u02aa\u02ac\u02b7\u02bf\u02c2\u02c4\u02c9\u02ce\u02d4\u02db"+ - "\u02e0\u02e6\u02e9\u02f1\u02f5\u037a\u037f\u0384\u0386\u038c\u03e1\u03e5"+ - "\u03ea\u03ef\u03f4\u03f6\u03fa\u03fc\u0449\u044d\u0452\u052c\u052e!\u0005"+ - "\u0002\u0000\u0005\u0004\u0000\u0005\u0006\u0000\u0005\u0001\u0000\u0005"+ - "\u0003\u0000\u0005\b\u0000\u0005\f\u0000\u0005\u000e\u0000\u0005\n\u0000"+ - "\u0005\u0005\u0000\u0005\u000b\u0000\u0000\u0001\u0000\u0007D\u0000\u0005"+ - "\u0000\u0000\u0007\u001d\u0000\u0004\u0000\u0000\u0007E\u0000\u0007&\u0000"+ - "\u0007$\u0000\u0007\u001e\u0000\u0007\u0019\u0000\u0007(\u0000\u0007O"+ - "\u0000\u0005\r\u0000\u0005\u0007\u0000\u0007G\u0000\u0007Y\u0000\u0007"+ - "X\u0000\u0007W\u0000\u0005\t\u0000\u0007F\u0000\u0005\u000f\u0000\u0007"+ - "!\u0000"; + "F\u00b6G\u00b8\u0000\u00baH\u00bcI\u00beJ\u00c0K\u00c2\u0000\u00c4\u0000"+ + "\u00c6\u0000\u00c8\u0000\u00ca\u0000\u00cc\u0000\u00ceL\u00d0\u0000\u00d2"+ + "M\u00d4N\u00d6O\u00d8\u0000\u00da\u0000\u00dc\u0000\u00de\u0000\u00e0"+ + "\u0000\u00e2P\u00e4Q\u00e6R\u00e8S\u00ea\u0000\u00ec\u0000\u00ee\u0000"+ + "\u00f0\u0000\u00f2T\u00f4\u0000\u00f6U\u00f8V\u00faW\u00fc\u0000\u00fe"+ + "\u0000\u0100X\u0102Y\u0104\u0000\u0106Z\u0108\u0000\u010a\u0000\u010c"+ + "[\u010e\\\u0110]\u0112\u0000\u0114\u0000\u0116\u0000\u0118\u0000\u011a"+ + "\u0000\u011c\u0000\u011e\u0000\u0120^\u0122_\u0124`\u0126\u0000\u0128"+ + "\u0000\u012a\u0000\u012c\u0000\u012e\u0000\u0130a\u0132b\u0134c\u0136"+ + "\u0000\u0138\u0000\u013a\u0000\u013c\u0000\u013ed\u0140e\u0142f\u0144"+ + "\u0000\u0146\u0000\u0148\u0000\u014a\u0000\u014cg\u014eh\u0150i\u0152"+ + "\u0000\u0154j\u0156k\u0158l\u015am\u015c\u0000\u015en\u0160o\u0162p\u0164"+ + "q\u0166\u0000\u0168r\u016as\u016ct\u016eu\u0170v\u0172\u0000\u0174\u0000"+ + "\u0176w\u0178x\u017ay\u017c\u0000\u017ez\u0180{\u0182|\u0184\u0000\u0186"+ + "\u0000\u0188\u0000\u018a\u0000\u0010\u0000\u0001\u0002\u0003\u0004\u0005"+ + "\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\r\u0006\u0000\t\n\r\r //[[]"+ + "]\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r \n\u0000\t\n\r\r ,,//==[["+ + "]]``||\u0002\u0000**//\u0001\u000009\u0002\u0000AZaz\u0005\u0000\"\"\\"+ + "\\nnrrtt\u0004\u0000\n\n\r\r\"\"\\\\\u0002\u0000EEee\u0002\u0000++--\u0001"+ + "\u0000``\u000b\u0000\t\n\r\r \"#,,//::<<>?\\\\||\u05a8\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\u00000\u0001\u0000\u0000\u0000\u00002\u0001\u0000\u0000"+ + "\u0000\u00004\u0001\u0000\u0000\u0000\u00006\u0001\u0000\u0000\u0000\u0000"+ + "8\u0001\u0000\u0000\u0000\u0000:\u0001\u0000\u0000\u0000\u0000<\u0001"+ + "\u0000\u0000\u0000\u0000>\u0001\u0000\u0000\u0000\u0000B\u0001\u0000\u0000"+ + "\u0000\u0001D\u0001\u0000\u0000\u0000\u0001F\u0001\u0000\u0000\u0000\u0001"+ + "H\u0001\u0000\u0000\u0000\u0001J\u0001\u0000\u0000\u0000\u0001L\u0001"+ + "\u0000\u0000\u0000\u0002N\u0001\u0000\u0000\u0000\u0002d\u0001\u0000\u0000"+ + "\u0000\u0002f\u0001\u0000\u0000\u0000\u0002h\u0001\u0000\u0000\u0000\u0002"+ + "j\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\u0002"+ + "x\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\u0002\u00a0\u0001\u0000"+ + "\u0000\u0000\u0002\u00a2\u0001\u0000\u0000\u0000\u0002\u00a4\u0001\u0000"+ + "\u0000\u0000\u0002\u00a6\u0001\u0000\u0000\u0000\u0002\u00a8\u0001\u0000"+ + "\u0000\u0000\u0002\u00aa\u0001\u0000\u0000\u0000\u0002\u00ac\u0001\u0000"+ + "\u0000\u0000\u0002\u00ae\u0001\u0000\u0000\u0000\u0002\u00b0\u0001\u0000"+ + "\u0000\u0000\u0002\u00b2\u0001\u0000\u0000\u0000\u0002\u00b4\u0001\u0000"+ + "\u0000\u0000\u0002\u00b6\u0001\u0000\u0000\u0000\u0002\u00ba\u0001\u0000"+ + "\u0000\u0000\u0002\u00bc\u0001\u0000\u0000\u0000\u0002\u00be\u0001\u0000"+ + "\u0000\u0000\u0002\u00c0\u0001\u0000\u0000\u0000\u0003\u00c2\u0001\u0000"+ + "\u0000\u0000\u0003\u00c4\u0001\u0000\u0000\u0000\u0003\u00c6\u0001\u0000"+ + "\u0000\u0000\u0003\u00c8\u0001\u0000\u0000\u0000\u0003\u00ca\u0001\u0000"+ + "\u0000\u0000\u0003\u00cc\u0001\u0000\u0000\u0000\u0003\u00ce\u0001\u0000"+ + "\u0000\u0000\u0003\u00d0\u0001\u0000\u0000\u0000\u0003\u00d2\u0001\u0000"+ + "\u0000\u0000\u0003\u00d4\u0001\u0000\u0000\u0000\u0003\u00d6\u0001\u0000"+ + "\u0000\u0000\u0004\u00d8\u0001\u0000\u0000\u0000\u0004\u00da\u0001\u0000"+ + "\u0000\u0000\u0004\u00dc\u0001\u0000\u0000\u0000\u0004\u00e2\u0001\u0000"+ + "\u0000\u0000\u0004\u00e4\u0001\u0000\u0000\u0000\u0004\u00e6\u0001\u0000"+ + "\u0000\u0000\u0004\u00e8\u0001\u0000\u0000\u0000\u0005\u00ea\u0001\u0000"+ + "\u0000\u0000\u0005\u00ec\u0001\u0000\u0000\u0000\u0005\u00ee\u0001\u0000"+ + "\u0000\u0000\u0005\u00f0\u0001\u0000\u0000\u0000\u0005\u00f2\u0001\u0000"+ + "\u0000\u0000\u0005\u00f4\u0001\u0000\u0000\u0000\u0005\u00f6\u0001\u0000"+ + "\u0000\u0000\u0005\u00f8\u0001\u0000\u0000\u0000\u0005\u00fa\u0001\u0000"+ + "\u0000\u0000\u0006\u00fc\u0001\u0000\u0000\u0000\u0006\u00fe\u0001\u0000"+ + "\u0000\u0000\u0006\u0100\u0001\u0000\u0000\u0000\u0006\u0102\u0001\u0000"+ + "\u0000\u0000\u0006\u0106\u0001\u0000\u0000\u0000\u0006\u0108\u0001\u0000"+ + "\u0000\u0000\u0006\u010a\u0001\u0000\u0000\u0000\u0006\u010c\u0001\u0000"+ + "\u0000\u0000\u0006\u010e\u0001\u0000\u0000\u0000\u0006\u0110\u0001\u0000"+ + "\u0000\u0000\u0007\u0112\u0001\u0000\u0000\u0000\u0007\u0114\u0001\u0000"+ + "\u0000\u0000\u0007\u0116\u0001\u0000\u0000\u0000\u0007\u0118\u0001\u0000"+ + "\u0000\u0000\u0007\u011a\u0001\u0000\u0000\u0000\u0007\u011c\u0001\u0000"+ + "\u0000\u0000\u0007\u011e\u0001\u0000\u0000\u0000\u0007\u0120\u0001\u0000"+ + "\u0000\u0000\u0007\u0122\u0001\u0000\u0000\u0000\u0007\u0124\u0001\u0000"+ + "\u0000\u0000\b\u0126\u0001\u0000\u0000\u0000\b\u0128\u0001\u0000\u0000"+ + "\u0000\b\u012a\u0001\u0000\u0000\u0000\b\u012c\u0001\u0000\u0000\u0000"+ + "\b\u012e\u0001\u0000\u0000\u0000\b\u0130\u0001\u0000\u0000\u0000\b\u0132"+ + "\u0001\u0000\u0000\u0000\b\u0134\u0001\u0000\u0000\u0000\t\u0136\u0001"+ + "\u0000\u0000\u0000\t\u0138\u0001\u0000\u0000\u0000\t\u013a\u0001\u0000"+ + "\u0000\u0000\t\u013c\u0001\u0000\u0000\u0000\t\u013e\u0001\u0000\u0000"+ + "\u0000\t\u0140\u0001\u0000\u0000\u0000\t\u0142\u0001\u0000\u0000\u0000"+ + "\n\u0144\u0001\u0000\u0000\u0000\n\u0146\u0001\u0000\u0000\u0000\n\u0148"+ + "\u0001\u0000\u0000\u0000\n\u014a\u0001\u0000\u0000\u0000\n\u014c\u0001"+ + "\u0000\u0000\u0000\n\u014e\u0001\u0000\u0000\u0000\n\u0150\u0001\u0000"+ + "\u0000\u0000\u000b\u0152\u0001\u0000\u0000\u0000\u000b\u0154\u0001\u0000"+ + "\u0000\u0000\u000b\u0156\u0001\u0000\u0000\u0000\u000b\u0158\u0001\u0000"+ + "\u0000\u0000\u000b\u015a\u0001\u0000\u0000\u0000\f\u015c\u0001\u0000\u0000"+ + "\u0000\f\u015e\u0001\u0000\u0000\u0000\f\u0160\u0001\u0000\u0000\u0000"+ + "\f\u0162\u0001\u0000\u0000\u0000\f\u0164\u0001\u0000\u0000\u0000\r\u0166"+ + "\u0001\u0000\u0000\u0000\r\u0168\u0001\u0000\u0000\u0000\r\u016a\u0001"+ + "\u0000\u0000\u0000\r\u016c\u0001\u0000\u0000\u0000\r\u016e\u0001\u0000"+ + "\u0000\u0000\r\u0170\u0001\u0000\u0000\u0000\u000e\u0172\u0001\u0000\u0000"+ + "\u0000\u000e\u0174\u0001\u0000\u0000\u0000\u000e\u0176\u0001\u0000\u0000"+ + "\u0000\u000e\u0178\u0001\u0000\u0000\u0000\u000e\u017a\u0001\u0000\u0000"+ + "\u0000\u000f\u017c\u0001\u0000\u0000\u0000\u000f\u017e\u0001\u0000\u0000"+ + "\u0000\u000f\u0180\u0001\u0000\u0000\u0000\u000f\u0182\u0001\u0000\u0000"+ + "\u0000\u000f\u0184\u0001\u0000\u0000\u0000\u000f\u0186\u0001\u0000\u0000"+ + "\u0000\u000f\u0188\u0001\u0000\u0000\u0000\u000f\u018a\u0001\u0000\u0000"+ + "\u0000\u0010\u018c\u0001\u0000\u0000\u0000\u0012\u0196\u0001\u0000\u0000"+ + "\u0000\u0014\u019d\u0001\u0000\u0000\u0000\u0016\u01a6\u0001\u0000\u0000"+ + "\u0000\u0018\u01ad\u0001\u0000\u0000\u0000\u001a\u01b7\u0001\u0000\u0000"+ + "\u0000\u001c\u01be\u0001\u0000\u0000\u0000\u001e\u01c5\u0001\u0000\u0000"+ + "\u0000 \u01d3\u0001\u0000\u0000\u0000\"\u01da\u0001\u0000\u0000\u0000"+ + "$\u01e2\u0001\u0000\u0000\u0000&\u01eb\u0001\u0000\u0000\u0000(\u01f2"+ + "\u0001\u0000\u0000\u0000*\u01fc\u0001\u0000\u0000\u0000,\u0208\u0001\u0000"+ + "\u0000\u0000.\u0211\u0001\u0000\u0000\u00000\u0217\u0001\u0000\u0000\u0000"+ + "2\u021e\u0001\u0000\u0000\u00004\u0225\u0001\u0000\u0000\u00006\u022d"+ + "\u0001\u0000\u0000\u00008\u0236\u0001\u0000\u0000\u0000:\u023c\u0001\u0000"+ + "\u0000\u0000<\u024d\u0001\u0000\u0000\u0000>\u025d\u0001\u0000\u0000\u0000"+ + "@\u0266\u0001\u0000\u0000\u0000B\u0269\u0001\u0000\u0000\u0000D\u026d"+ + "\u0001\u0000\u0000\u0000F\u0272\u0001\u0000\u0000\u0000H\u0277\u0001\u0000"+ + "\u0000\u0000J\u027b\u0001\u0000\u0000\u0000L\u027f\u0001\u0000\u0000\u0000"+ + "N\u0283\u0001\u0000\u0000\u0000P\u0287\u0001\u0000\u0000\u0000R\u0289"+ + "\u0001\u0000\u0000\u0000T\u028b\u0001\u0000\u0000\u0000V\u028e\u0001\u0000"+ + "\u0000\u0000X\u0290\u0001\u0000\u0000\u0000Z\u0299\u0001\u0000\u0000\u0000"+ + "\\\u029b\u0001\u0000\u0000\u0000^\u02a0\u0001\u0000\u0000\u0000`\u02a2"+ + "\u0001\u0000\u0000\u0000b\u02a7\u0001\u0000\u0000\u0000d\u02c6\u0001\u0000"+ + "\u0000\u0000f\u02c9\u0001\u0000\u0000\u0000h\u02f7\u0001\u0000\u0000\u0000"+ + "j\u02f9\u0001\u0000\u0000\u0000l\u02fc\u0001\u0000\u0000\u0000n\u0300"+ + "\u0001\u0000\u0000\u0000p\u0304\u0001\u0000\u0000\u0000r\u0306\u0001\u0000"+ + "\u0000\u0000t\u0309\u0001\u0000\u0000\u0000v\u030b\u0001\u0000\u0000\u0000"+ + "x\u0310\u0001\u0000\u0000\u0000z\u0312\u0001\u0000\u0000\u0000|\u0318"+ + "\u0001\u0000\u0000\u0000~\u031e\u0001\u0000\u0000\u0000\u0080\u0323\u0001"+ + "\u0000\u0000\u0000\u0082\u0325\u0001\u0000\u0000\u0000\u0084\u0328\u0001"+ + "\u0000\u0000\u0000\u0086\u032b\u0001\u0000\u0000\u0000\u0088\u0330\u0001"+ + "\u0000\u0000\u0000\u008a\u0334\u0001\u0000\u0000\u0000\u008c\u0339\u0001"+ + "\u0000\u0000\u0000\u008e\u033f\u0001\u0000\u0000\u0000\u0090\u0342\u0001"+ + "\u0000\u0000\u0000\u0092\u0344\u0001\u0000\u0000\u0000\u0094\u034a\u0001"+ + "\u0000\u0000\u0000\u0096\u034c\u0001\u0000\u0000\u0000\u0098\u0351\u0001"+ + "\u0000\u0000\u0000\u009a\u0354\u0001\u0000\u0000\u0000\u009c\u0357\u0001"+ + "\u0000\u0000\u0000\u009e\u035a\u0001\u0000\u0000\u0000\u00a0\u035c\u0001"+ + "\u0000\u0000\u0000\u00a2\u035f\u0001\u0000\u0000\u0000\u00a4\u0361\u0001"+ + "\u0000\u0000\u0000\u00a6\u0364\u0001\u0000\u0000\u0000\u00a8\u0366\u0001"+ + "\u0000\u0000\u0000\u00aa\u0368\u0001\u0000\u0000\u0000\u00ac\u036a\u0001"+ + "\u0000\u0000\u0000\u00ae\u036c\u0001\u0000\u0000\u0000\u00b0\u037c\u0001"+ + "\u0000\u0000\u0000\u00b2\u037e\u0001\u0000\u0000\u0000\u00b4\u0383\u0001"+ + "\u0000\u0000\u0000\u00b6\u0398\u0001\u0000\u0000\u0000\u00b8\u039a\u0001"+ + "\u0000\u0000\u0000\u00ba\u03a2\u0001\u0000\u0000\u0000\u00bc\u03a4\u0001"+ + "\u0000\u0000\u0000\u00be\u03a8\u0001\u0000\u0000\u0000\u00c0\u03ac\u0001"+ + "\u0000\u0000\u0000\u00c2\u03b0\u0001\u0000\u0000\u0000\u00c4\u03b5\u0001"+ + "\u0000\u0000\u0000\u00c6\u03b9\u0001\u0000\u0000\u0000\u00c8\u03bd\u0001"+ + "\u0000\u0000\u0000\u00ca\u03c1\u0001\u0000\u0000\u0000\u00cc\u03c5\u0001"+ + "\u0000\u0000\u0000\u00ce\u03c9\u0001\u0000\u0000\u0000\u00d0\u03d2\u0001"+ + "\u0000\u0000\u0000\u00d2\u03d6\u0001\u0000\u0000\u0000\u00d4\u03da\u0001"+ + "\u0000\u0000\u0000\u00d6\u03de\u0001\u0000\u0000\u0000\u00d8\u03e2\u0001"+ + "\u0000\u0000\u0000\u00da\u03e7\u0001\u0000\u0000\u0000\u00dc\u03eb\u0001"+ + "\u0000\u0000\u0000\u00de\u03f3\u0001\u0000\u0000\u0000\u00e0\u0408\u0001"+ + "\u0000\u0000\u0000\u00e2\u040c\u0001\u0000\u0000\u0000\u00e4\u0410\u0001"+ + "\u0000\u0000\u0000\u00e6\u0414\u0001\u0000\u0000\u0000\u00e8\u0418\u0001"+ + "\u0000\u0000\u0000\u00ea\u041c\u0001\u0000\u0000\u0000\u00ec\u0421\u0001"+ + "\u0000\u0000\u0000\u00ee\u0425\u0001\u0000\u0000\u0000\u00f0\u0429\u0001"+ + "\u0000\u0000\u0000\u00f2\u042d\u0001\u0000\u0000\u0000\u00f4\u0430\u0001"+ + "\u0000\u0000\u0000\u00f6\u0434\u0001\u0000\u0000\u0000\u00f8\u0438\u0001"+ + "\u0000\u0000\u0000\u00fa\u043c\u0001\u0000\u0000\u0000\u00fc\u0440\u0001"+ + "\u0000\u0000\u0000\u00fe\u0445\u0001\u0000\u0000\u0000\u0100\u044a\u0001"+ + "\u0000\u0000\u0000\u0102\u044f\u0001\u0000\u0000\u0000\u0104\u0456\u0001"+ + "\u0000\u0000\u0000\u0106\u045f\u0001\u0000\u0000\u0000\u0108\u0466\u0001"+ + "\u0000\u0000\u0000\u010a\u046a\u0001\u0000\u0000\u0000\u010c\u046e\u0001"+ + "\u0000\u0000\u0000\u010e\u0472\u0001\u0000\u0000\u0000\u0110\u0476\u0001"+ + "\u0000\u0000\u0000\u0112\u047a\u0001\u0000\u0000\u0000\u0114\u0480\u0001"+ + "\u0000\u0000\u0000\u0116\u0484\u0001\u0000\u0000\u0000\u0118\u0488\u0001"+ + "\u0000\u0000\u0000\u011a\u048c\u0001\u0000\u0000\u0000\u011c\u0490\u0001"+ + "\u0000\u0000\u0000\u011e\u0494\u0001\u0000\u0000\u0000\u0120\u0498\u0001"+ + "\u0000\u0000\u0000\u0122\u049c\u0001\u0000\u0000\u0000\u0124\u04a0\u0001"+ + "\u0000\u0000\u0000\u0126\u04a4\u0001\u0000\u0000\u0000\u0128\u04a9\u0001"+ + "\u0000\u0000\u0000\u012a\u04ad\u0001\u0000\u0000\u0000\u012c\u04b1\u0001"+ + "\u0000\u0000\u0000\u012e\u04b6\u0001\u0000\u0000\u0000\u0130\u04ba\u0001"+ + "\u0000\u0000\u0000\u0132\u04be\u0001\u0000\u0000\u0000\u0134\u04c2\u0001"+ + "\u0000\u0000\u0000\u0136\u04c6\u0001\u0000\u0000\u0000\u0138\u04cc\u0001"+ + "\u0000\u0000\u0000\u013a\u04d0\u0001\u0000\u0000\u0000\u013c\u04d4\u0001"+ + "\u0000\u0000\u0000\u013e\u04d8\u0001\u0000\u0000\u0000\u0140\u04dc\u0001"+ + "\u0000\u0000\u0000\u0142\u04e0\u0001\u0000\u0000\u0000\u0144\u04e4\u0001"+ + "\u0000\u0000\u0000\u0146\u04e9\u0001\u0000\u0000\u0000\u0148\u04ed\u0001"+ + "\u0000\u0000\u0000\u014a\u04f1\u0001\u0000\u0000\u0000\u014c\u04f5\u0001"+ + "\u0000\u0000\u0000\u014e\u04f9\u0001\u0000\u0000\u0000\u0150\u04fd\u0001"+ + "\u0000\u0000\u0000\u0152\u0501\u0001\u0000\u0000\u0000\u0154\u0506\u0001"+ + "\u0000\u0000\u0000\u0156\u050b\u0001\u0000\u0000\u0000\u0158\u050f\u0001"+ + "\u0000\u0000\u0000\u015a\u0513\u0001\u0000\u0000\u0000\u015c\u0517\u0001"+ + "\u0000\u0000\u0000\u015e\u051c\u0001\u0000\u0000\u0000\u0160\u0526\u0001"+ + "\u0000\u0000\u0000\u0162\u052a\u0001\u0000\u0000\u0000\u0164\u052e\u0001"+ + "\u0000\u0000\u0000\u0166\u0532\u0001\u0000\u0000\u0000\u0168\u0537\u0001"+ + "\u0000\u0000\u0000\u016a\u053e\u0001\u0000\u0000\u0000\u016c\u0542\u0001"+ + "\u0000\u0000\u0000\u016e\u0546\u0001\u0000\u0000\u0000\u0170\u054a\u0001"+ + "\u0000\u0000\u0000\u0172\u054e\u0001\u0000\u0000\u0000\u0174\u0553\u0001"+ + "\u0000\u0000\u0000\u0176\u0559\u0001\u0000\u0000\u0000\u0178\u055d\u0001"+ + "\u0000\u0000\u0000\u017a\u0561\u0001\u0000\u0000\u0000\u017c\u0565\u0001"+ + "\u0000\u0000\u0000\u017e\u056b\u0001\u0000\u0000\u0000\u0180\u056f\u0001"+ + "\u0000\u0000\u0000\u0182\u0573\u0001\u0000\u0000\u0000\u0184\u0577\u0001"+ + "\u0000\u0000\u0000\u0186\u057d\u0001\u0000\u0000\u0000\u0188\u0583\u0001"+ + "\u0000\u0000\u0000\u018a\u0589\u0001\u0000\u0000\u0000\u018c\u018d\u0005"+ + "d\u0000\u0000\u018d\u018e\u0005i\u0000\u0000\u018e\u018f\u0005s\u0000"+ + "\u0000\u018f\u0190\u0005s\u0000\u0000\u0190\u0191\u0005e\u0000\u0000\u0191"+ + "\u0192\u0005c\u0000\u0000\u0192\u0193\u0005t\u0000\u0000\u0193\u0194\u0001"+ + "\u0000\u0000\u0000\u0194\u0195\u0006\u0000\u0000\u0000\u0195\u0011\u0001"+ + "\u0000\u0000\u0000\u0196\u0197\u0005d\u0000\u0000\u0197\u0198\u0005r\u0000"+ + "\u0000\u0198\u0199\u0005o\u0000\u0000\u0199\u019a\u0005p\u0000\u0000\u019a"+ + "\u019b\u0001\u0000\u0000\u0000\u019b\u019c\u0006\u0001\u0001\u0000\u019c"+ + "\u0013\u0001\u0000\u0000\u0000\u019d\u019e\u0005e\u0000\u0000\u019e\u019f"+ + "\u0005n\u0000\u0000\u019f\u01a0\u0005r\u0000\u0000\u01a0\u01a1\u0005i"+ + "\u0000\u0000\u01a1\u01a2\u0005c\u0000\u0000\u01a2\u01a3\u0005h\u0000\u0000"+ + "\u01a3\u01a4\u0001\u0000\u0000\u0000\u01a4\u01a5\u0006\u0002\u0002\u0000"+ + "\u01a5\u0015\u0001\u0000\u0000\u0000\u01a6\u01a7\u0005e\u0000\u0000\u01a7"+ + "\u01a8\u0005v\u0000\u0000\u01a8\u01a9\u0005a\u0000\u0000\u01a9\u01aa\u0005"+ + "l\u0000\u0000\u01aa\u01ab\u0001\u0000\u0000\u0000\u01ab\u01ac\u0006\u0003"+ + "\u0000\u0000\u01ac\u0017\u0001\u0000\u0000\u0000\u01ad\u01ae\u0005e\u0000"+ + "\u0000\u01ae\u01af\u0005x\u0000\u0000\u01af\u01b0\u0005p\u0000\u0000\u01b0"+ + "\u01b1\u0005l\u0000\u0000\u01b1\u01b2\u0005a\u0000\u0000\u01b2\u01b3\u0005"+ + "i\u0000\u0000\u01b3\u01b4\u0005n\u0000\u0000\u01b4\u01b5\u0001\u0000\u0000"+ + "\u0000\u01b5\u01b6\u0006\u0004\u0003\u0000\u01b6\u0019\u0001\u0000\u0000"+ + "\u0000\u01b7\u01b8\u0005f\u0000\u0000\u01b8\u01b9\u0005r\u0000\u0000\u01b9"+ + "\u01ba\u0005o\u0000\u0000\u01ba\u01bb\u0005m\u0000\u0000\u01bb\u01bc\u0001"+ + "\u0000\u0000\u0000\u01bc\u01bd\u0006\u0005\u0004\u0000\u01bd\u001b\u0001"+ + "\u0000\u0000\u0000\u01be\u01bf\u0005g\u0000\u0000\u01bf\u01c0\u0005r\u0000"+ + "\u0000\u01c0\u01c1\u0005o\u0000\u0000\u01c1\u01c2\u0005k\u0000\u0000\u01c2"+ + "\u01c3\u0001\u0000\u0000\u0000\u01c3\u01c4\u0006\u0006\u0000\u0000\u01c4"+ + "\u001d\u0001\u0000\u0000\u0000\u01c5\u01c6\u0005i\u0000\u0000\u01c6\u01c7"+ + "\u0005n\u0000\u0000\u01c7\u01c8\u0005l\u0000\u0000\u01c8\u01c9\u0005i"+ + "\u0000\u0000\u01c9\u01ca\u0005n\u0000\u0000\u01ca\u01cb\u0005e\u0000\u0000"+ + "\u01cb\u01cc\u0005s\u0000\u0000\u01cc\u01cd\u0005t\u0000\u0000\u01cd\u01ce"+ + "\u0005a\u0000\u0000\u01ce\u01cf\u0005t\u0000\u0000\u01cf\u01d0\u0005s"+ + "\u0000\u0000\u01d0\u01d1\u0001\u0000\u0000\u0000\u01d1\u01d2\u0006\u0007"+ + "\u0000\u0000\u01d2\u001f\u0001\u0000\u0000\u0000\u01d3\u01d4\u0005k\u0000"+ + "\u0000\u01d4\u01d5\u0005e\u0000\u0000\u01d5\u01d6\u0005e\u0000\u0000\u01d6"+ + "\u01d7\u0005p\u0000\u0000\u01d7\u01d8\u0001\u0000\u0000\u0000\u01d8\u01d9"+ + "\u0006\b\u0001\u0000\u01d9!\u0001\u0000\u0000\u0000\u01da\u01db\u0005"+ + "l\u0000\u0000\u01db\u01dc\u0005i\u0000\u0000\u01dc\u01dd\u0005m\u0000"+ + "\u0000\u01dd\u01de\u0005i\u0000\u0000\u01de\u01df\u0005t\u0000\u0000\u01df"+ + "\u01e0\u0001\u0000\u0000\u0000\u01e0\u01e1\u0006\t\u0000\u0000\u01e1#"+ + "\u0001\u0000\u0000\u0000\u01e2\u01e3\u0005l\u0000\u0000\u01e3\u01e4\u0005"+ + "o\u0000\u0000\u01e4\u01e5\u0005o\u0000\u0000\u01e5\u01e6\u0005k\u0000"+ + "\u0000\u01e6\u01e7\u0005u\u0000\u0000\u01e7\u01e8\u0005p\u0000\u0000\u01e8"+ + "\u01e9\u0001\u0000\u0000\u0000\u01e9\u01ea\u0006\n\u0005\u0000\u01ea%"+ + "\u0001\u0000\u0000\u0000\u01eb\u01ec\u0005m\u0000\u0000\u01ec\u01ed\u0005"+ + "e\u0000\u0000\u01ed\u01ee\u0005t\u0000\u0000\u01ee\u01ef\u0005a\u0000"+ + "\u0000\u01ef\u01f0\u0001\u0000\u0000\u0000\u01f0\u01f1\u0006\u000b\u0006"+ + "\u0000\u01f1\'\u0001\u0000\u0000\u0000\u01f2\u01f3\u0005m\u0000\u0000"+ + "\u01f3\u01f4\u0005e\u0000\u0000\u01f4\u01f5\u0005t\u0000\u0000\u01f5\u01f6"+ + "\u0005r\u0000\u0000\u01f6\u01f7\u0005i\u0000\u0000\u01f7\u01f8\u0005c"+ + "\u0000\u0000\u01f8\u01f9\u0005s\u0000\u0000\u01f9\u01fa\u0001\u0000\u0000"+ + "\u0000\u01fa\u01fb\u0006\f\u0007\u0000\u01fb)\u0001\u0000\u0000\u0000"+ + "\u01fc\u01fd\u0005m\u0000\u0000\u01fd\u01fe\u0005v\u0000\u0000\u01fe\u01ff"+ + "\u0005_\u0000\u0000\u01ff\u0200\u0005e\u0000\u0000\u0200\u0201\u0005x"+ + "\u0000\u0000\u0201\u0202\u0005p\u0000\u0000\u0202\u0203\u0005a\u0000\u0000"+ + "\u0203\u0204\u0005n\u0000\u0000\u0204\u0205\u0005d\u0000\u0000\u0205\u0206"+ + "\u0001\u0000\u0000\u0000\u0206\u0207\u0006\r\b\u0000\u0207+\u0001\u0000"+ + "\u0000\u0000\u0208\u0209\u0005r\u0000\u0000\u0209\u020a\u0005e\u0000\u0000"+ + "\u020a\u020b\u0005n\u0000\u0000\u020b\u020c\u0005a\u0000\u0000\u020c\u020d"+ + "\u0005m\u0000\u0000\u020d\u020e\u0005e\u0000\u0000\u020e\u020f\u0001\u0000"+ + "\u0000\u0000\u020f\u0210\u0006\u000e\t\u0000\u0210-\u0001\u0000\u0000"+ + "\u0000\u0211\u0212\u0005r\u0000\u0000\u0212\u0213\u0005o\u0000\u0000\u0213"+ + "\u0214\u0005w\u0000\u0000\u0214\u0215\u0001\u0000\u0000\u0000\u0215\u0216"+ + "\u0006\u000f\u0000\u0000\u0216/\u0001\u0000\u0000\u0000\u0217\u0218\u0005"+ + "s\u0000\u0000\u0218\u0219\u0005h\u0000\u0000\u0219\u021a\u0005o\u0000"+ + "\u0000\u021a\u021b\u0005w\u0000\u0000\u021b\u021c\u0001\u0000\u0000\u0000"+ + "\u021c\u021d\u0006\u0010\n\u0000\u021d1\u0001\u0000\u0000\u0000\u021e"+ + "\u021f\u0005s\u0000\u0000\u021f\u0220\u0005o\u0000\u0000\u0220\u0221\u0005"+ + "r\u0000\u0000\u0221\u0222\u0005t\u0000\u0000\u0222\u0223\u0001\u0000\u0000"+ + "\u0000\u0223\u0224\u0006\u0011\u0000\u0000\u02243\u0001\u0000\u0000\u0000"+ + "\u0225\u0226\u0005s\u0000\u0000\u0226\u0227\u0005t\u0000\u0000\u0227\u0228"+ + "\u0005a\u0000\u0000\u0228\u0229\u0005t\u0000\u0000\u0229\u022a\u0005s"+ + "\u0000\u0000\u022a\u022b\u0001\u0000\u0000\u0000\u022b\u022c\u0006\u0012"+ + "\u0000\u0000\u022c5\u0001\u0000\u0000\u0000\u022d\u022e\u0005w\u0000\u0000"+ + "\u022e\u022f\u0005h\u0000\u0000\u022f\u0230\u0005e\u0000\u0000\u0230\u0231"+ + "\u0005r\u0000\u0000\u0231\u0232\u0005e\u0000\u0000\u0232\u0233\u0001\u0000"+ + "\u0000\u0000\u0233\u0234\u0006\u0013\u0000\u0000\u02347\u0001\u0000\u0000"+ + "\u0000\u0235\u0237\b\u0000\u0000\u0000\u0236\u0235\u0001\u0000\u0000\u0000"+ + "\u0237\u0238\u0001\u0000\u0000\u0000\u0238\u0236\u0001\u0000\u0000\u0000"+ + "\u0238\u0239\u0001\u0000\u0000\u0000\u0239\u023a\u0001\u0000\u0000\u0000"+ + "\u023a\u023b\u0006\u0014\u0000\u0000\u023b9\u0001\u0000\u0000\u0000\u023c"+ + "\u023d\u0005/\u0000\u0000\u023d\u023e\u0005/\u0000\u0000\u023e\u0242\u0001"+ + "\u0000\u0000\u0000\u023f\u0241\b\u0001\u0000\u0000\u0240\u023f\u0001\u0000"+ + "\u0000\u0000\u0241\u0244\u0001\u0000\u0000\u0000\u0242\u0240\u0001\u0000"+ + "\u0000\u0000\u0242\u0243\u0001\u0000\u0000\u0000\u0243\u0246\u0001\u0000"+ + "\u0000\u0000\u0244\u0242\u0001\u0000\u0000\u0000\u0245\u0247\u0005\r\u0000"+ + "\u0000\u0246\u0245\u0001\u0000\u0000\u0000\u0246\u0247\u0001\u0000\u0000"+ + "\u0000\u0247\u0249\u0001\u0000\u0000\u0000\u0248\u024a\u0005\n\u0000\u0000"+ + "\u0249\u0248\u0001\u0000\u0000\u0000\u0249\u024a\u0001\u0000\u0000\u0000"+ + "\u024a\u024b\u0001\u0000\u0000\u0000\u024b\u024c\u0006\u0015\u000b\u0000"+ + "\u024c;\u0001\u0000\u0000\u0000\u024d\u024e\u0005/\u0000\u0000\u024e\u024f"+ + "\u0005*\u0000\u0000\u024f\u0254\u0001\u0000\u0000\u0000\u0250\u0253\u0003"+ + "<\u0016\u0000\u0251\u0253\t\u0000\u0000\u0000\u0252\u0250\u0001\u0000"+ + "\u0000\u0000\u0252\u0251\u0001\u0000\u0000\u0000\u0253\u0256\u0001\u0000"+ + "\u0000\u0000\u0254\u0255\u0001\u0000\u0000\u0000\u0254\u0252\u0001\u0000"+ + "\u0000\u0000\u0255\u0257\u0001\u0000\u0000\u0000\u0256\u0254\u0001\u0000"+ + "\u0000\u0000\u0257\u0258\u0005*\u0000\u0000\u0258\u0259\u0005/\u0000\u0000"+ + "\u0259\u025a\u0001\u0000\u0000\u0000\u025a\u025b\u0006\u0016\u000b\u0000"+ + "\u025b=\u0001\u0000\u0000\u0000\u025c\u025e\u0007\u0002\u0000\u0000\u025d"+ + "\u025c\u0001\u0000\u0000\u0000\u025e\u025f\u0001\u0000\u0000\u0000\u025f"+ + "\u025d\u0001\u0000\u0000\u0000\u025f\u0260\u0001\u0000\u0000\u0000\u0260"+ + "\u0261\u0001\u0000\u0000\u0000\u0261\u0262\u0006\u0017\u000b\u0000\u0262"+ + "?\u0001\u0000\u0000\u0000\u0263\u0267\b\u0003\u0000\u0000\u0264\u0265"+ + "\u0005/\u0000\u0000\u0265\u0267\b\u0004\u0000\u0000\u0266\u0263\u0001"+ + "\u0000\u0000\u0000\u0266\u0264\u0001\u0000\u0000\u0000\u0267A\u0001\u0000"+ + "\u0000\u0000\u0268\u026a\u0003@\u0018\u0000\u0269\u0268\u0001\u0000\u0000"+ + "\u0000\u026a\u026b\u0001\u0000\u0000\u0000\u026b\u0269\u0001\u0000\u0000"+ + "\u0000\u026b\u026c\u0001\u0000\u0000\u0000\u026cC\u0001\u0000\u0000\u0000"+ + "\u026d\u026e\u0003\u00b2Q\u0000\u026e\u026f\u0001\u0000\u0000\u0000\u026f"+ + "\u0270\u0006\u001a\f\u0000\u0270\u0271\u0006\u001a\r\u0000\u0271E\u0001"+ + "\u0000\u0000\u0000\u0272\u0273\u0003N\u001f\u0000\u0273\u0274\u0001\u0000"+ + "\u0000\u0000\u0274\u0275\u0006\u001b\u000e\u0000\u0275\u0276\u0006\u001b"+ + "\u000f\u0000\u0276G\u0001\u0000\u0000\u0000\u0277\u0278\u0003>\u0017\u0000"+ + "\u0278\u0279\u0001\u0000\u0000\u0000\u0279\u027a\u0006\u001c\u000b\u0000"+ + "\u027aI\u0001\u0000\u0000\u0000\u027b\u027c\u0003:\u0015\u0000\u027c\u027d"+ + "\u0001\u0000\u0000\u0000\u027d\u027e\u0006\u001d\u000b\u0000\u027eK\u0001"+ + "\u0000\u0000\u0000\u027f\u0280\u0003<\u0016\u0000\u0280\u0281\u0001\u0000"+ + "\u0000\u0000\u0281\u0282\u0006\u001e\u000b\u0000\u0282M\u0001\u0000\u0000"+ + "\u0000\u0283\u0284\u0005|\u0000\u0000\u0284\u0285\u0001\u0000\u0000\u0000"+ + "\u0285\u0286\u0006\u001f\u000f\u0000\u0286O\u0001\u0000\u0000\u0000\u0287"+ + "\u0288\u0007\u0005\u0000\u0000\u0288Q\u0001\u0000\u0000\u0000\u0289\u028a"+ + "\u0007\u0006\u0000\u0000\u028aS\u0001\u0000\u0000\u0000\u028b\u028c\u0005"+ + "\\\u0000\u0000\u028c\u028d\u0007\u0007\u0000\u0000\u028dU\u0001\u0000"+ + "\u0000\u0000\u028e\u028f\b\b\u0000\u0000\u028fW\u0001\u0000\u0000\u0000"+ + "\u0290\u0292\u0007\t\u0000\u0000\u0291\u0293\u0007\n\u0000\u0000\u0292"+ + "\u0291\u0001\u0000\u0000\u0000\u0292\u0293\u0001\u0000\u0000\u0000\u0293"+ + "\u0295\u0001\u0000\u0000\u0000\u0294\u0296\u0003P \u0000\u0295\u0294\u0001"+ + "\u0000\u0000\u0000\u0296\u0297\u0001\u0000\u0000\u0000\u0297\u0295\u0001"+ + "\u0000\u0000\u0000\u0297\u0298\u0001\u0000\u0000\u0000\u0298Y\u0001\u0000"+ + "\u0000\u0000\u0299\u029a\u0005@\u0000\u0000\u029a[\u0001\u0000\u0000\u0000"+ + "\u029b\u029c\u0005`\u0000\u0000\u029c]\u0001\u0000\u0000\u0000\u029d\u02a1"+ + "\b\u000b\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_\u0001\u0000\u0000\u0000\u02a2\u02a3\u0005_\u0000\u0000"+ + "\u02a3a\u0001\u0000\u0000\u0000\u02a4\u02a8\u0003R!\u0000\u02a5\u02a8"+ + "\u0003P \u0000\u02a6\u02a8\u0003`(\u0000\u02a7\u02a4\u0001\u0000\u0000"+ + "\u0000\u02a7\u02a5\u0001\u0000\u0000\u0000\u02a7\u02a6\u0001\u0000\u0000"+ + "\u0000\u02a8c\u0001\u0000\u0000\u0000\u02a9\u02ae\u0005\"\u0000\u0000"+ + "\u02aa\u02ad\u0003T\"\u0000\u02ab\u02ad\u0003V#\u0000\u02ac\u02aa\u0001"+ + "\u0000\u0000\u0000\u02ac\u02ab\u0001\u0000\u0000\u0000\u02ad\u02b0\u0001"+ + "\u0000\u0000\u0000\u02ae\u02ac\u0001\u0000\u0000\u0000\u02ae\u02af\u0001"+ + "\u0000\u0000\u0000\u02af\u02b1\u0001\u0000\u0000\u0000\u02b0\u02ae\u0001"+ + "\u0000\u0000\u0000\u02b1\u02c7\u0005\"\u0000\u0000\u02b2\u02b3\u0005\""+ + "\u0000\u0000\u02b3\u02b4\u0005\"\u0000\u0000\u02b4\u02b5\u0005\"\u0000"+ + "\u0000\u02b5\u02b9\u0001\u0000\u0000\u0000\u02b6\u02b8\b\u0001\u0000\u0000"+ + "\u02b7\u02b6\u0001\u0000\u0000\u0000\u02b8\u02bb\u0001\u0000\u0000\u0000"+ + "\u02b9\u02ba\u0001\u0000\u0000\u0000\u02b9\u02b7\u0001\u0000\u0000\u0000"+ + "\u02ba\u02bc\u0001\u0000\u0000\u0000\u02bb\u02b9\u0001\u0000\u0000\u0000"+ + "\u02bc\u02bd\u0005\"\u0000\u0000\u02bd\u02be\u0005\"\u0000\u0000\u02be"+ + "\u02bf\u0005\"\u0000\u0000\u02bf\u02c1\u0001\u0000\u0000\u0000\u02c0\u02c2"+ + "\u0005\"\u0000\u0000\u02c1\u02c0\u0001\u0000\u0000\u0000\u02c1\u02c2\u0001"+ + "\u0000\u0000\u0000\u02c2\u02c4\u0001\u0000\u0000\u0000\u02c3\u02c5\u0005"+ + "\"\u0000\u0000\u02c4\u02c3\u0001\u0000\u0000\u0000\u02c4\u02c5\u0001\u0000"+ + "\u0000\u0000\u02c5\u02c7\u0001\u0000\u0000\u0000\u02c6\u02a9\u0001\u0000"+ + "\u0000\u0000\u02c6\u02b2\u0001\u0000\u0000\u0000\u02c7e\u0001\u0000\u0000"+ + "\u0000\u02c8\u02ca\u0003P \u0000\u02c9\u02c8\u0001\u0000\u0000\u0000\u02ca"+ + "\u02cb\u0001\u0000\u0000\u0000\u02cb\u02c9\u0001\u0000\u0000\u0000\u02cb"+ + "\u02cc\u0001\u0000\u0000\u0000\u02ccg\u0001\u0000\u0000\u0000\u02cd\u02cf"+ + "\u0003P \u0000\u02ce\u02cd\u0001\u0000\u0000\u0000\u02cf\u02d0\u0001\u0000"+ + "\u0000\u0000\u02d0\u02ce\u0001\u0000\u0000\u0000\u02d0\u02d1\u0001\u0000"+ + "\u0000\u0000\u02d1\u02d2\u0001\u0000\u0000\u0000\u02d2\u02d6\u0003x4\u0000"+ + "\u02d3\u02d5\u0003P \u0000\u02d4\u02d3\u0001\u0000\u0000\u0000\u02d5\u02d8"+ + "\u0001\u0000\u0000\u0000\u02d6\u02d4\u0001\u0000\u0000\u0000\u02d6\u02d7"+ + "\u0001\u0000\u0000\u0000\u02d7\u02f8\u0001\u0000\u0000\u0000\u02d8\u02d6"+ + "\u0001\u0000\u0000\u0000\u02d9\u02db\u0003x4\u0000\u02da\u02dc\u0003P"+ + " \u0000\u02db\u02da\u0001\u0000\u0000\u0000\u02dc\u02dd\u0001\u0000\u0000"+ + "\u0000\u02dd\u02db\u0001\u0000\u0000\u0000\u02dd\u02de\u0001\u0000\u0000"+ + "\u0000\u02de\u02f8\u0001\u0000\u0000\u0000\u02df\u02e1\u0003P \u0000\u02e0"+ + "\u02df\u0001\u0000\u0000\u0000\u02e1\u02e2\u0001\u0000\u0000\u0000\u02e2"+ + "\u02e0\u0001\u0000\u0000\u0000\u02e2\u02e3\u0001\u0000\u0000\u0000\u02e3"+ + "\u02eb\u0001\u0000\u0000\u0000\u02e4\u02e8\u0003x4\u0000\u02e5\u02e7\u0003"+ + "P \u0000\u02e6\u02e5\u0001\u0000\u0000\u0000\u02e7\u02ea\u0001\u0000\u0000"+ + "\u0000\u02e8\u02e6\u0001\u0000\u0000\u0000\u02e8\u02e9\u0001\u0000\u0000"+ + "\u0000\u02e9\u02ec\u0001\u0000\u0000\u0000\u02ea\u02e8\u0001\u0000\u0000"+ + "\u0000\u02eb\u02e4\u0001\u0000\u0000\u0000\u02eb\u02ec\u0001\u0000\u0000"+ + "\u0000\u02ec\u02ed\u0001\u0000\u0000\u0000\u02ed\u02ee\u0003X$\u0000\u02ee"+ + "\u02f8\u0001\u0000\u0000\u0000\u02ef\u02f1\u0003x4\u0000\u02f0\u02f2\u0003"+ + "P \u0000\u02f1\u02f0\u0001\u0000\u0000\u0000\u02f2\u02f3\u0001\u0000\u0000"+ + "\u0000\u02f3\u02f1\u0001\u0000\u0000\u0000\u02f3\u02f4\u0001\u0000\u0000"+ + "\u0000\u02f4\u02f5\u0001\u0000\u0000\u0000\u02f5\u02f6\u0003X$\u0000\u02f6"+ + "\u02f8\u0001\u0000\u0000\u0000\u02f7\u02ce\u0001\u0000\u0000\u0000\u02f7"+ + "\u02d9\u0001\u0000\u0000\u0000\u02f7\u02e0\u0001\u0000\u0000\u0000\u02f7"+ + "\u02ef\u0001\u0000\u0000\u0000\u02f8i\u0001\u0000\u0000\u0000\u02f9\u02fa"+ + "\u0005b\u0000\u0000\u02fa\u02fb\u0005y\u0000\u0000\u02fbk\u0001\u0000"+ + "\u0000\u0000\u02fc\u02fd\u0005a\u0000\u0000\u02fd\u02fe\u0005n\u0000\u0000"+ + "\u02fe\u02ff\u0005d\u0000\u0000\u02ffm\u0001\u0000\u0000\u0000\u0300\u0301"+ + "\u0005a\u0000\u0000\u0301\u0302\u0005s\u0000\u0000\u0302\u0303\u0005c"+ + "\u0000\u0000\u0303o\u0001\u0000\u0000\u0000\u0304\u0305\u0005=\u0000\u0000"+ + "\u0305q\u0001\u0000\u0000\u0000\u0306\u0307\u0005:\u0000\u0000\u0307\u0308"+ + "\u0005:\u0000\u0000\u0308s\u0001\u0000\u0000\u0000\u0309\u030a\u0005,"+ + "\u0000\u0000\u030au\u0001\u0000\u0000\u0000\u030b\u030c\u0005d\u0000\u0000"+ + "\u030c\u030d\u0005e\u0000\u0000\u030d\u030e\u0005s\u0000\u0000\u030e\u030f"+ + "\u0005c\u0000\u0000\u030fw\u0001\u0000\u0000\u0000\u0310\u0311\u0005."+ + "\u0000\u0000\u0311y\u0001\u0000\u0000\u0000\u0312\u0313\u0005f\u0000\u0000"+ + "\u0313\u0314\u0005a\u0000\u0000\u0314\u0315\u0005l\u0000\u0000\u0315\u0316"+ + "\u0005s\u0000\u0000\u0316\u0317\u0005e\u0000\u0000\u0317{\u0001\u0000"+ + "\u0000\u0000\u0318\u0319\u0005f\u0000\u0000\u0319\u031a\u0005i\u0000\u0000"+ + "\u031a\u031b\u0005r\u0000\u0000\u031b\u031c\u0005s\u0000\u0000\u031c\u031d"+ + "\u0005t\u0000\u0000\u031d}\u0001\u0000\u0000\u0000\u031e\u031f\u0005l"+ + "\u0000\u0000\u031f\u0320\u0005a\u0000\u0000\u0320\u0321\u0005s\u0000\u0000"+ + "\u0321\u0322\u0005t\u0000\u0000\u0322\u007f\u0001\u0000\u0000\u0000\u0323"+ + "\u0324\u0005(\u0000\u0000\u0324\u0081\u0001\u0000\u0000\u0000\u0325\u0326"+ + "\u0005i\u0000\u0000\u0326\u0327\u0005n\u0000\u0000\u0327\u0083\u0001\u0000"+ + "\u0000\u0000\u0328\u0329\u0005i\u0000\u0000\u0329\u032a\u0005s\u0000\u0000"+ + "\u032a\u0085\u0001\u0000\u0000\u0000\u032b\u032c\u0005l\u0000\u0000\u032c"+ + "\u032d\u0005i\u0000\u0000\u032d\u032e\u0005k\u0000\u0000\u032e\u032f\u0005"+ + "e\u0000\u0000\u032f\u0087\u0001\u0000\u0000\u0000\u0330\u0331\u0005n\u0000"+ + "\u0000\u0331\u0332\u0005o\u0000\u0000\u0332\u0333\u0005t\u0000\u0000\u0333"+ + "\u0089\u0001\u0000\u0000\u0000\u0334\u0335\u0005n\u0000\u0000\u0335\u0336"+ + "\u0005u\u0000\u0000\u0336\u0337\u0005l\u0000\u0000\u0337\u0338\u0005l"+ + "\u0000\u0000\u0338\u008b\u0001\u0000\u0000\u0000\u0339\u033a\u0005n\u0000"+ + "\u0000\u033a\u033b\u0005u\u0000\u0000\u033b\u033c\u0005l\u0000\u0000\u033c"+ + "\u033d\u0005l\u0000\u0000\u033d\u033e\u0005s\u0000\u0000\u033e\u008d\u0001"+ + "\u0000\u0000\u0000\u033f\u0340\u0005o\u0000\u0000\u0340\u0341\u0005r\u0000"+ + "\u0000\u0341\u008f\u0001\u0000\u0000\u0000\u0342\u0343\u0005?\u0000\u0000"+ + "\u0343\u0091\u0001\u0000\u0000\u0000\u0344\u0345\u0005r\u0000\u0000\u0345"+ + "\u0346\u0005l\u0000\u0000\u0346\u0347\u0005i\u0000\u0000\u0347\u0348\u0005"+ + "k\u0000\u0000\u0348\u0349\u0005e\u0000\u0000\u0349\u0093\u0001\u0000\u0000"+ + "\u0000\u034a\u034b\u0005)\u0000\u0000\u034b\u0095\u0001\u0000\u0000\u0000"+ + "\u034c\u034d\u0005t\u0000\u0000\u034d\u034e\u0005r\u0000\u0000\u034e\u034f"+ + "\u0005u\u0000\u0000\u034f\u0350\u0005e\u0000\u0000\u0350\u0097\u0001\u0000"+ + "\u0000\u0000\u0351\u0352\u0005=\u0000\u0000\u0352\u0353\u0005=\u0000\u0000"+ + "\u0353\u0099\u0001\u0000\u0000\u0000\u0354\u0355\u0005=\u0000\u0000\u0355"+ + "\u0356\u0005~\u0000\u0000\u0356\u009b\u0001\u0000\u0000\u0000\u0357\u0358"+ + "\u0005!\u0000\u0000\u0358\u0359\u0005=\u0000\u0000\u0359\u009d\u0001\u0000"+ + "\u0000\u0000\u035a\u035b\u0005<\u0000\u0000\u035b\u009f\u0001\u0000\u0000"+ + "\u0000\u035c\u035d\u0005<\u0000\u0000\u035d\u035e\u0005=\u0000\u0000\u035e"+ + "\u00a1\u0001\u0000\u0000\u0000\u035f\u0360\u0005>\u0000\u0000\u0360\u00a3"+ + "\u0001\u0000\u0000\u0000\u0361\u0362\u0005>\u0000\u0000\u0362\u0363\u0005"+ + "=\u0000\u0000\u0363\u00a5\u0001\u0000\u0000\u0000\u0364\u0365\u0005+\u0000"+ + "\u0000\u0365\u00a7\u0001\u0000\u0000\u0000\u0366\u0367\u0005-\u0000\u0000"+ + "\u0367\u00a9\u0001\u0000\u0000\u0000\u0368\u0369\u0005*\u0000\u0000\u0369"+ + "\u00ab\u0001\u0000\u0000\u0000\u036a\u036b\u0005/\u0000\u0000\u036b\u00ad"+ + "\u0001\u0000\u0000\u0000\u036c\u036d\u0005%\u0000\u0000\u036d\u00af\u0001"+ + "\u0000\u0000\u0000\u036e\u036f\u0003\u0090@\u0000\u036f\u0373\u0003R!"+ + "\u0000\u0370\u0372\u0003b)\u0000\u0371\u0370\u0001\u0000\u0000\u0000\u0372"+ + "\u0375\u0001\u0000\u0000\u0000\u0373\u0371\u0001\u0000\u0000\u0000\u0373"+ + "\u0374\u0001\u0000\u0000\u0000\u0374\u037d\u0001\u0000\u0000\u0000\u0375"+ + "\u0373\u0001\u0000\u0000\u0000\u0376\u0378\u0003\u0090@\u0000\u0377\u0379"+ + "\u0003P \u0000\u0378\u0377\u0001\u0000\u0000\u0000\u0379\u037a\u0001\u0000"+ + "\u0000\u0000\u037a\u0378\u0001\u0000\u0000\u0000\u037a\u037b\u0001\u0000"+ + "\u0000\u0000\u037b\u037d\u0001\u0000\u0000\u0000\u037c\u036e\u0001\u0000"+ + "\u0000\u0000\u037c\u0376\u0001\u0000\u0000\u0000\u037d\u00b1\u0001\u0000"+ + "\u0000\u0000\u037e\u037f\u0005[\u0000\u0000\u037f\u0380\u0001\u0000\u0000"+ + "\u0000\u0380\u0381\u0006Q\u0000\u0000\u0381\u0382\u0006Q\u0000\u0000\u0382"+ + "\u00b3\u0001\u0000\u0000\u0000\u0383\u0384\u0005]\u0000\u0000\u0384\u0385"+ + "\u0001\u0000\u0000\u0000\u0385\u0386\u0006R\u000f\u0000\u0386\u0387\u0006"+ + "R\u000f\u0000\u0387\u00b5\u0001\u0000\u0000\u0000\u0388\u038c\u0003R!"+ + "\u0000\u0389\u038b\u0003b)\u0000\u038a\u0389\u0001\u0000\u0000\u0000\u038b"+ + "\u038e\u0001\u0000\u0000\u0000\u038c\u038a\u0001\u0000\u0000\u0000\u038c"+ + "\u038d\u0001\u0000\u0000\u0000\u038d\u0399\u0001\u0000\u0000\u0000\u038e"+ + "\u038c\u0001\u0000\u0000\u0000\u038f\u0392\u0003`(\u0000\u0390\u0392\u0003"+ + "Z%\u0000\u0391\u038f\u0001\u0000\u0000\u0000\u0391\u0390\u0001\u0000\u0000"+ + "\u0000\u0392\u0394\u0001\u0000\u0000\u0000\u0393\u0395\u0003b)\u0000\u0394"+ + "\u0393\u0001\u0000\u0000\u0000\u0395\u0396\u0001\u0000\u0000\u0000\u0396"+ + "\u0394\u0001\u0000\u0000\u0000\u0396\u0397\u0001\u0000\u0000\u0000\u0397"+ + "\u0399\u0001\u0000\u0000\u0000\u0398\u0388\u0001\u0000\u0000\u0000\u0398"+ + "\u0391\u0001\u0000\u0000\u0000\u0399\u00b7\u0001\u0000\u0000\u0000\u039a"+ + "\u039c\u0003\\&\u0000\u039b\u039d\u0003^\'\u0000\u039c\u039b\u0001\u0000"+ + "\u0000\u0000\u039d\u039e\u0001\u0000\u0000\u0000\u039e\u039c\u0001\u0000"+ + "\u0000\u0000\u039e\u039f\u0001\u0000\u0000\u0000\u039f\u03a0\u0001\u0000"+ + "\u0000\u0000\u03a0\u03a1\u0003\\&\u0000\u03a1\u00b9\u0001\u0000\u0000"+ + "\u0000\u03a2\u03a3\u0003\u00b8T\u0000\u03a3\u00bb\u0001\u0000\u0000\u0000"+ + "\u03a4\u03a5\u0003:\u0015\u0000\u03a5\u03a6\u0001\u0000\u0000\u0000\u03a6"+ + "\u03a7\u0006V\u000b\u0000\u03a7\u00bd\u0001\u0000\u0000\u0000\u03a8\u03a9"+ + "\u0003<\u0016\u0000\u03a9\u03aa\u0001\u0000\u0000\u0000\u03aa\u03ab\u0006"+ + "W\u000b\u0000\u03ab\u00bf\u0001\u0000\u0000\u0000\u03ac\u03ad\u0003>\u0017"+ + "\u0000\u03ad\u03ae\u0001\u0000\u0000\u0000\u03ae\u03af\u0006X\u000b\u0000"+ + "\u03af\u00c1\u0001\u0000\u0000\u0000\u03b0\u03b1\u0003N\u001f\u0000\u03b1"+ + "\u03b2\u0001\u0000\u0000\u0000\u03b2\u03b3\u0006Y\u000e\u0000\u03b3\u03b4"+ + "\u0006Y\u000f\u0000\u03b4\u00c3\u0001\u0000\u0000\u0000\u03b5\u03b6\u0003"+ + "\u00b2Q\u0000\u03b6\u03b7\u0001\u0000\u0000\u0000\u03b7\u03b8\u0006Z\f"+ + "\u0000\u03b8\u00c5\u0001\u0000\u0000\u0000\u03b9\u03ba\u0003\u00b4R\u0000"+ + "\u03ba\u03bb\u0001\u0000\u0000\u0000\u03bb\u03bc\u0006[\u0010\u0000\u03bc"+ + "\u00c7\u0001\u0000\u0000\u0000\u03bd\u03be\u0003t2\u0000\u03be\u03bf\u0001"+ + "\u0000\u0000\u0000\u03bf\u03c0\u0006\\\u0011\u0000\u03c0\u00c9\u0001\u0000"+ + "\u0000\u0000\u03c1\u03c2\u0003p0\u0000\u03c2\u03c3\u0001\u0000\u0000\u0000"+ + "\u03c3\u03c4\u0006]\u0012\u0000\u03c4\u00cb\u0001\u0000\u0000\u0000\u03c5"+ + "\u03c6\u0003d*\u0000\u03c6\u03c7\u0001\u0000\u0000\u0000\u03c7\u03c8\u0006"+ + "^\u0013\u0000\u03c8\u00cd\u0001\u0000\u0000\u0000\u03c9\u03ca\u0005m\u0000"+ + "\u0000\u03ca\u03cb\u0005e\u0000\u0000\u03cb\u03cc\u0005t\u0000\u0000\u03cc"+ + "\u03cd\u0005a\u0000\u0000\u03cd\u03ce\u0005d\u0000\u0000\u03ce\u03cf\u0005"+ + "a\u0000\u0000\u03cf\u03d0\u0005t\u0000\u0000\u03d0\u03d1\u0005a\u0000"+ + "\u0000\u03d1\u00cf\u0001\u0000\u0000\u0000\u03d2\u03d3\u0003B\u0019\u0000"+ + "\u03d3\u03d4\u0001\u0000\u0000\u0000\u03d4\u03d5\u0006`\u0014\u0000\u03d5"+ + "\u00d1\u0001\u0000\u0000\u0000\u03d6\u03d7\u0003:\u0015\u0000\u03d7\u03d8"+ + "\u0001\u0000\u0000\u0000\u03d8\u03d9\u0006a\u000b\u0000\u03d9\u00d3\u0001"+ + "\u0000\u0000\u0000\u03da\u03db\u0003<\u0016\u0000\u03db\u03dc\u0001\u0000"+ + "\u0000\u0000\u03dc\u03dd\u0006b\u000b\u0000\u03dd\u00d5\u0001\u0000\u0000"+ + "\u0000\u03de\u03df\u0003>\u0017\u0000\u03df\u03e0\u0001\u0000\u0000\u0000"+ + "\u03e0\u03e1\u0006c\u000b\u0000\u03e1\u00d7\u0001\u0000\u0000\u0000\u03e2"+ + "\u03e3\u0003N\u001f\u0000\u03e3\u03e4\u0001\u0000\u0000\u0000\u03e4\u03e5"+ + "\u0006d\u000e\u0000\u03e5\u03e6\u0006d\u000f\u0000\u03e6\u00d9\u0001\u0000"+ + "\u0000\u0000\u03e7\u03e8\u0003x4\u0000\u03e8\u03e9\u0001\u0000\u0000\u0000"+ + "\u03e9\u03ea\u0006e\u0015\u0000\u03ea\u00db\u0001\u0000\u0000\u0000\u03eb"+ + "\u03ec\u0003t2\u0000\u03ec\u03ed\u0001\u0000\u0000\u0000\u03ed\u03ee\u0006"+ + "f\u0011\u0000\u03ee\u00dd\u0001\u0000\u0000\u0000\u03ef\u03f4\u0003R!"+ + "\u0000\u03f0\u03f4\u0003P \u0000\u03f1\u03f4\u0003`(\u0000\u03f2\u03f4"+ + "\u0003\u00aaM\u0000\u03f3\u03ef\u0001\u0000\u0000\u0000\u03f3\u03f0\u0001"+ + "\u0000\u0000\u0000\u03f3\u03f1\u0001\u0000\u0000\u0000\u03f3\u03f2\u0001"+ + "\u0000\u0000\u0000\u03f4\u00df\u0001\u0000\u0000\u0000\u03f5\u03f8\u0003"+ + "R!\u0000\u03f6\u03f8\u0003\u00aaM\u0000\u03f7\u03f5\u0001\u0000\u0000"+ + "\u0000\u03f7\u03f6\u0001\u0000\u0000\u0000\u03f8\u03fc\u0001\u0000\u0000"+ + "\u0000\u03f9\u03fb\u0003\u00deg\u0000\u03fa\u03f9\u0001\u0000\u0000\u0000"+ + "\u03fb\u03fe\u0001\u0000\u0000\u0000\u03fc\u03fa\u0001\u0000\u0000\u0000"+ + "\u03fc\u03fd\u0001\u0000\u0000\u0000\u03fd\u0409\u0001\u0000\u0000\u0000"+ + "\u03fe\u03fc\u0001\u0000\u0000\u0000\u03ff\u0402\u0003`(\u0000\u0400\u0402"+ + "\u0003Z%\u0000\u0401\u03ff\u0001\u0000\u0000\u0000\u0401\u0400\u0001\u0000"+ + "\u0000\u0000\u0402\u0404\u0001\u0000\u0000\u0000\u0403\u0405\u0003\u00de"+ + "g\u0000\u0404\u0403\u0001\u0000\u0000\u0000\u0405\u0406\u0001\u0000\u0000"+ + "\u0000\u0406\u0404\u0001\u0000\u0000\u0000\u0406\u0407\u0001\u0000\u0000"+ + "\u0000\u0407\u0409\u0001\u0000\u0000\u0000\u0408\u03f7\u0001\u0000\u0000"+ + "\u0000\u0408\u0401\u0001\u0000\u0000\u0000\u0409\u00e1\u0001\u0000\u0000"+ + "\u0000\u040a\u040d\u0003\u00e0h\u0000\u040b\u040d\u0003\u00b8T\u0000\u040c"+ + "\u040a\u0001\u0000\u0000\u0000\u040c\u040b\u0001\u0000\u0000\u0000\u040d"+ + "\u040e\u0001\u0000\u0000\u0000\u040e\u040c\u0001\u0000\u0000\u0000\u040e"+ + "\u040f\u0001\u0000\u0000\u0000\u040f\u00e3\u0001\u0000\u0000\u0000\u0410"+ + "\u0411\u0003:\u0015\u0000\u0411\u0412\u0001\u0000\u0000\u0000\u0412\u0413"+ + "\u0006j\u000b\u0000\u0413\u00e5\u0001\u0000\u0000\u0000\u0414\u0415\u0003"+ + "<\u0016\u0000\u0415\u0416\u0001\u0000\u0000\u0000\u0416\u0417\u0006k\u000b"+ + "\u0000\u0417\u00e7\u0001\u0000\u0000\u0000\u0418\u0419\u0003>\u0017\u0000"+ + "\u0419\u041a\u0001\u0000\u0000\u0000\u041a\u041b\u0006l\u000b\u0000\u041b"+ + "\u00e9\u0001\u0000\u0000\u0000\u041c\u041d\u0003N\u001f\u0000\u041d\u041e"+ + "\u0001\u0000\u0000\u0000\u041e\u041f\u0006m\u000e\u0000\u041f\u0420\u0006"+ + "m\u000f\u0000\u0420\u00eb\u0001\u0000\u0000\u0000\u0421\u0422\u0003p0"+ + "\u0000\u0422\u0423\u0001\u0000\u0000\u0000\u0423\u0424\u0006n\u0012\u0000"+ + "\u0424\u00ed\u0001\u0000\u0000\u0000\u0425\u0426\u0003t2\u0000\u0426\u0427"+ + "\u0001\u0000\u0000\u0000\u0427\u0428\u0006o\u0011\u0000\u0428\u00ef\u0001"+ + "\u0000\u0000\u0000\u0429\u042a\u0003x4\u0000\u042a\u042b\u0001\u0000\u0000"+ + "\u0000\u042b\u042c\u0006p\u0015\u0000\u042c\u00f1\u0001\u0000\u0000\u0000"+ + "\u042d\u042e\u0005a\u0000\u0000\u042e\u042f\u0005s\u0000\u0000\u042f\u00f3"+ + "\u0001\u0000\u0000\u0000\u0430\u0431\u0003\u00e2i\u0000\u0431\u0432\u0001"+ + "\u0000\u0000\u0000\u0432\u0433\u0006r\u0016\u0000\u0433\u00f5\u0001\u0000"+ + "\u0000\u0000\u0434\u0435\u0003:\u0015\u0000\u0435\u0436\u0001\u0000\u0000"+ + "\u0000\u0436\u0437\u0006s\u000b\u0000\u0437\u00f7\u0001\u0000\u0000\u0000"+ + "\u0438\u0439\u0003<\u0016\u0000\u0439\u043a\u0001\u0000\u0000\u0000\u043a"+ + "\u043b\u0006t\u000b\u0000\u043b\u00f9\u0001\u0000\u0000\u0000\u043c\u043d"+ + "\u0003>\u0017\u0000\u043d\u043e\u0001\u0000\u0000\u0000\u043e\u043f\u0006"+ + "u\u000b\u0000\u043f\u00fb\u0001\u0000\u0000\u0000\u0440\u0441\u0003N\u001f"+ + "\u0000\u0441\u0442\u0001\u0000\u0000\u0000\u0442\u0443\u0006v\u000e\u0000"+ + "\u0443\u0444\u0006v\u000f\u0000\u0444\u00fd\u0001\u0000\u0000\u0000\u0445"+ + "\u0446\u0003\u00b2Q\u0000\u0446\u0447\u0001\u0000\u0000\u0000\u0447\u0448"+ + "\u0006w\f\u0000\u0448\u0449\u0006w\u0017\u0000\u0449\u00ff\u0001\u0000"+ + "\u0000\u0000\u044a\u044b\u0005o\u0000\u0000\u044b\u044c\u0005n\u0000\u0000"+ + "\u044c\u044d\u0001\u0000\u0000\u0000\u044d\u044e\u0006x\u0018\u0000\u044e"+ + "\u0101\u0001\u0000\u0000\u0000\u044f\u0450\u0005w\u0000\u0000\u0450\u0451"+ + "\u0005i\u0000\u0000\u0451\u0452\u0005t\u0000\u0000\u0452\u0453\u0005h"+ + "\u0000\u0000\u0453\u0454\u0001\u0000\u0000\u0000\u0454\u0455\u0006y\u0018"+ + "\u0000\u0455\u0103\u0001\u0000\u0000\u0000\u0456\u0457\b\f\u0000\u0000"+ + "\u0457\u0105\u0001\u0000\u0000\u0000\u0458\u045a\u0003\u0104z\u0000\u0459"+ + "\u0458\u0001\u0000\u0000\u0000\u045a\u045b\u0001\u0000\u0000\u0000\u045b"+ + "\u0459\u0001\u0000\u0000\u0000\u045b\u045c\u0001\u0000\u0000\u0000\u045c"+ + "\u045d\u0001\u0000\u0000\u0000\u045d\u045e\u0003\u0168\u00ac\u0000\u045e"+ + "\u0460\u0001\u0000\u0000\u0000\u045f\u0459\u0001\u0000\u0000\u0000\u045f"+ + "\u0460\u0001\u0000\u0000\u0000\u0460\u0462\u0001\u0000\u0000\u0000\u0461"+ + "\u0463\u0003\u0104z\u0000\u0462\u0461\u0001\u0000\u0000\u0000\u0463\u0464"+ + "\u0001\u0000\u0000\u0000\u0464\u0462\u0001\u0000\u0000\u0000\u0464\u0465"+ + "\u0001\u0000\u0000\u0000\u0465\u0107\u0001\u0000\u0000\u0000\u0466\u0467"+ + "\u0003\u00baU\u0000\u0467\u0468\u0001\u0000\u0000\u0000\u0468\u0469\u0006"+ + "|\u0019\u0000\u0469\u0109\u0001\u0000\u0000\u0000\u046a\u046b\u0003\u0106"+ + "{\u0000\u046b\u046c\u0001\u0000\u0000\u0000\u046c\u046d\u0006}\u001a\u0000"+ + "\u046d\u010b\u0001\u0000\u0000\u0000\u046e\u046f\u0003:\u0015\u0000\u046f"+ + "\u0470\u0001\u0000\u0000\u0000\u0470\u0471\u0006~\u000b\u0000\u0471\u010d"+ + "\u0001\u0000\u0000\u0000\u0472\u0473\u0003<\u0016\u0000\u0473\u0474\u0001"+ + "\u0000\u0000\u0000\u0474\u0475\u0006\u007f\u000b\u0000\u0475\u010f\u0001"+ + "\u0000\u0000\u0000\u0476\u0477\u0003>\u0017\u0000\u0477\u0478\u0001\u0000"+ + "\u0000\u0000\u0478\u0479\u0006\u0080\u000b\u0000\u0479\u0111\u0001\u0000"+ + "\u0000\u0000\u047a\u047b\u0003N\u001f\u0000\u047b\u047c\u0001\u0000\u0000"+ + "\u0000\u047c\u047d\u0006\u0081\u000e\u0000\u047d\u047e\u0006\u0081\u000f"+ + "\u0000\u047e\u047f\u0006\u0081\u000f\u0000\u047f\u0113\u0001\u0000\u0000"+ + "\u0000\u0480\u0481\u0003p0\u0000\u0481\u0482\u0001\u0000\u0000\u0000\u0482"+ + "\u0483\u0006\u0082\u0012\u0000\u0483\u0115\u0001\u0000\u0000\u0000\u0484"+ + "\u0485\u0003t2\u0000\u0485\u0486\u0001\u0000\u0000\u0000\u0486\u0487\u0006"+ + "\u0083\u0011\u0000\u0487\u0117\u0001\u0000\u0000\u0000\u0488\u0489\u0003"+ + "x4\u0000\u0489\u048a\u0001\u0000\u0000\u0000\u048a\u048b\u0006\u0084\u0015"+ + "\u0000\u048b\u0119\u0001\u0000\u0000\u0000\u048c\u048d\u0003\u0102y\u0000"+ + "\u048d\u048e\u0001\u0000\u0000\u0000\u048e\u048f\u0006\u0085\u001b\u0000"+ + "\u048f\u011b\u0001\u0000\u0000\u0000\u0490\u0491\u0003\u00e2i\u0000\u0491"+ + "\u0492\u0001\u0000\u0000\u0000\u0492\u0493\u0006\u0086\u0016\u0000\u0493"+ + "\u011d\u0001\u0000\u0000\u0000\u0494\u0495\u0003\u00baU\u0000\u0495\u0496"+ + "\u0001\u0000\u0000\u0000\u0496\u0497\u0006\u0087\u0019\u0000\u0497\u011f"+ + "\u0001\u0000\u0000\u0000\u0498\u0499\u0003:\u0015\u0000\u0499\u049a\u0001"+ + "\u0000\u0000\u0000\u049a\u049b\u0006\u0088\u000b\u0000\u049b\u0121\u0001"+ + "\u0000\u0000\u0000\u049c\u049d\u0003<\u0016\u0000\u049d\u049e\u0001\u0000"+ + "\u0000\u0000\u049e\u049f\u0006\u0089\u000b\u0000\u049f\u0123\u0001\u0000"+ + "\u0000\u0000\u04a0\u04a1\u0003>\u0017\u0000\u04a1\u04a2\u0001\u0000\u0000"+ + "\u0000\u04a2\u04a3\u0006\u008a\u000b\u0000\u04a3\u0125\u0001\u0000\u0000"+ + "\u0000\u04a4\u04a5\u0003N\u001f\u0000\u04a5\u04a6\u0001\u0000\u0000\u0000"+ + "\u04a6\u04a7\u0006\u008b\u000e\u0000\u04a7\u04a8\u0006\u008b\u000f\u0000"+ + "\u04a8\u0127\u0001\u0000\u0000\u0000\u04a9\u04aa\u0003t2\u0000\u04aa\u04ab"+ + "\u0001\u0000\u0000\u0000\u04ab\u04ac\u0006\u008c\u0011\u0000\u04ac\u0129"+ + "\u0001\u0000\u0000\u0000\u04ad\u04ae\u0003x4\u0000\u04ae\u04af\u0001\u0000"+ + "\u0000\u0000\u04af\u04b0\u0006\u008d\u0015\u0000\u04b0\u012b\u0001\u0000"+ + "\u0000\u0000\u04b1\u04b2\u0003\u0100x\u0000\u04b2\u04b3\u0001\u0000\u0000"+ + "\u0000\u04b3\u04b4\u0006\u008e\u001c\u0000\u04b4\u04b5\u0006\u008e\u001d"+ + "\u0000\u04b5\u012d\u0001\u0000\u0000\u0000\u04b6\u04b7\u0003B\u0019\u0000"+ + "\u04b7\u04b8\u0001\u0000\u0000\u0000\u04b8\u04b9\u0006\u008f\u0014\u0000"+ + "\u04b9\u012f\u0001\u0000\u0000\u0000\u04ba\u04bb\u0003:\u0015\u0000\u04bb"+ + "\u04bc\u0001\u0000\u0000\u0000\u04bc\u04bd\u0006\u0090\u000b\u0000\u04bd"+ + "\u0131\u0001\u0000\u0000\u0000\u04be\u04bf\u0003<\u0016\u0000\u04bf\u04c0"+ + "\u0001\u0000\u0000\u0000\u04c0\u04c1\u0006\u0091\u000b\u0000\u04c1\u0133"+ + "\u0001\u0000\u0000\u0000\u04c2\u04c3\u0003>\u0017\u0000\u04c3\u04c4\u0001"+ + "\u0000\u0000\u0000\u04c4\u04c5\u0006\u0092\u000b\u0000\u04c5\u0135\u0001"+ + "\u0000\u0000\u0000\u04c6\u04c7\u0003N\u001f\u0000\u04c7\u04c8\u0001\u0000"+ + "\u0000\u0000\u04c8\u04c9\u0006\u0093\u000e\u0000\u04c9\u04ca\u0006\u0093"+ + "\u000f\u0000\u04ca\u04cb\u0006\u0093\u000f\u0000\u04cb\u0137\u0001\u0000"+ + "\u0000\u0000\u04cc\u04cd\u0003t2\u0000\u04cd\u04ce\u0001\u0000\u0000\u0000"+ + "\u04ce\u04cf\u0006\u0094\u0011\u0000\u04cf\u0139\u0001\u0000\u0000\u0000"+ + "\u04d0\u04d1\u0003x4\u0000\u04d1\u04d2\u0001\u0000\u0000\u0000\u04d2\u04d3"+ + "\u0006\u0095\u0015\u0000\u04d3\u013b\u0001\u0000\u0000\u0000\u04d4\u04d5"+ + "\u0003\u00e2i\u0000\u04d5\u04d6\u0001\u0000\u0000\u0000\u04d6\u04d7\u0006"+ + "\u0096\u0016\u0000\u04d7\u013d\u0001\u0000\u0000\u0000\u04d8\u04d9\u0003"+ + ":\u0015\u0000\u04d9\u04da\u0001\u0000\u0000\u0000\u04da\u04db\u0006\u0097"+ + "\u000b\u0000\u04db\u013f\u0001\u0000\u0000\u0000\u04dc\u04dd\u0003<\u0016"+ + "\u0000\u04dd\u04de\u0001\u0000\u0000\u0000\u04de\u04df\u0006\u0098\u000b"+ + "\u0000\u04df\u0141\u0001\u0000\u0000\u0000\u04e0\u04e1\u0003>\u0017\u0000"+ + "\u04e1\u04e2\u0001\u0000\u0000\u0000\u04e2\u04e3\u0006\u0099\u000b\u0000"+ + "\u04e3\u0143\u0001\u0000\u0000\u0000\u04e4\u04e5\u0003N\u001f\u0000\u04e5"+ + "\u04e6\u0001\u0000\u0000\u0000\u04e6\u04e7\u0006\u009a\u000e\u0000\u04e7"+ + "\u04e8\u0006\u009a\u000f\u0000\u04e8\u0145\u0001\u0000\u0000\u0000\u04e9"+ + "\u04ea\u0003x4\u0000\u04ea\u04eb\u0001\u0000\u0000\u0000\u04eb\u04ec\u0006"+ + "\u009b\u0015\u0000\u04ec\u0147\u0001\u0000\u0000\u0000\u04ed\u04ee\u0003"+ + "\u00baU\u0000\u04ee\u04ef\u0001\u0000\u0000\u0000\u04ef\u04f0\u0006\u009c"+ + "\u0019\u0000\u04f0\u0149\u0001\u0000\u0000\u0000\u04f1\u04f2\u0003\u00b6"+ + "S\u0000\u04f2\u04f3\u0001\u0000\u0000\u0000\u04f3\u04f4\u0006\u009d\u001e"+ + "\u0000\u04f4\u014b\u0001\u0000\u0000\u0000\u04f5\u04f6\u0003:\u0015\u0000"+ + "\u04f6\u04f7\u0001\u0000\u0000\u0000\u04f7\u04f8\u0006\u009e\u000b\u0000"+ + "\u04f8\u014d\u0001\u0000\u0000\u0000\u04f9\u04fa\u0003<\u0016\u0000\u04fa"+ + "\u04fb\u0001\u0000\u0000\u0000\u04fb\u04fc\u0006\u009f\u000b\u0000\u04fc"+ + "\u014f\u0001\u0000\u0000\u0000\u04fd\u04fe\u0003>\u0017\u0000\u04fe\u04ff"+ + "\u0001\u0000\u0000\u0000\u04ff\u0500\u0006\u00a0\u000b\u0000\u0500\u0151"+ + "\u0001\u0000\u0000\u0000\u0501\u0502\u0003N\u001f\u0000\u0502\u0503\u0001"+ + "\u0000\u0000\u0000\u0503\u0504\u0006\u00a1\u000e\u0000\u0504\u0505\u0006"+ + "\u00a1\u000f\u0000\u0505\u0153\u0001\u0000\u0000\u0000\u0506\u0507\u0005"+ + "i\u0000\u0000\u0507\u0508\u0005n\u0000\u0000\u0508\u0509\u0005f\u0000"+ + "\u0000\u0509\u050a\u0005o\u0000\u0000\u050a\u0155\u0001\u0000\u0000\u0000"+ + "\u050b\u050c\u0003:\u0015\u0000\u050c\u050d\u0001\u0000\u0000\u0000\u050d"+ + "\u050e\u0006\u00a3\u000b\u0000\u050e\u0157\u0001\u0000\u0000\u0000\u050f"+ + "\u0510\u0003<\u0016\u0000\u0510\u0511\u0001\u0000\u0000\u0000\u0511\u0512"+ + "\u0006\u00a4\u000b\u0000\u0512\u0159\u0001\u0000\u0000\u0000\u0513\u0514"+ + "\u0003>\u0017\u0000\u0514\u0515\u0001\u0000\u0000\u0000\u0515\u0516\u0006"+ + "\u00a5\u000b\u0000\u0516\u015b\u0001\u0000\u0000\u0000\u0517\u0518\u0003"+ + "N\u001f\u0000\u0518\u0519\u0001\u0000\u0000\u0000\u0519\u051a\u0006\u00a6"+ + "\u000e\u0000\u051a\u051b\u0006\u00a6\u000f\u0000\u051b\u015d\u0001\u0000"+ + "\u0000\u0000\u051c\u051d\u0005f\u0000\u0000\u051d\u051e\u0005u\u0000\u0000"+ + "\u051e\u051f\u0005n\u0000\u0000\u051f\u0520\u0005c\u0000\u0000\u0520\u0521"+ + "\u0005t\u0000\u0000\u0521\u0522\u0005i\u0000\u0000\u0522\u0523\u0005o"+ + "\u0000\u0000\u0523\u0524\u0005n\u0000\u0000\u0524\u0525\u0005s\u0000\u0000"+ + "\u0525\u015f\u0001\u0000\u0000\u0000\u0526\u0527\u0003:\u0015\u0000\u0527"+ + "\u0528\u0001\u0000\u0000\u0000\u0528\u0529\u0006\u00a8\u000b\u0000\u0529"+ + "\u0161\u0001\u0000\u0000\u0000\u052a\u052b\u0003<\u0016\u0000\u052b\u052c"+ + "\u0001\u0000\u0000\u0000\u052c\u052d\u0006\u00a9\u000b\u0000\u052d\u0163"+ + "\u0001\u0000\u0000\u0000\u052e\u052f\u0003>\u0017\u0000\u052f\u0530\u0001"+ + "\u0000\u0000\u0000\u0530\u0531\u0006\u00aa\u000b\u0000\u0531\u0165\u0001"+ + "\u0000\u0000\u0000\u0532\u0533\u0003\u00b4R\u0000\u0533\u0534\u0001\u0000"+ + "\u0000\u0000\u0534\u0535\u0006\u00ab\u0010\u0000\u0535\u0536\u0006\u00ab"+ + "\u000f\u0000\u0536\u0167\u0001\u0000\u0000\u0000\u0537\u0538\u0005:\u0000"+ + "\u0000\u0538\u0169\u0001\u0000\u0000\u0000\u0539\u053f\u0003Z%\u0000\u053a"+ + "\u053f\u0003P \u0000\u053b\u053f\u0003x4\u0000\u053c\u053f\u0003R!\u0000"+ + "\u053d\u053f\u0003`(\u0000\u053e\u0539\u0001\u0000\u0000\u0000\u053e\u053a"+ + "\u0001\u0000\u0000\u0000\u053e\u053b\u0001\u0000\u0000\u0000\u053e\u053c"+ + "\u0001\u0000\u0000\u0000\u053e\u053d\u0001\u0000\u0000\u0000\u053f\u0540"+ + "\u0001\u0000\u0000\u0000\u0540\u053e\u0001\u0000\u0000\u0000\u0540\u0541"+ + "\u0001\u0000\u0000\u0000\u0541\u016b\u0001\u0000\u0000\u0000\u0542\u0543"+ + "\u0003:\u0015\u0000\u0543\u0544\u0001\u0000\u0000\u0000\u0544\u0545\u0006"+ + "\u00ae\u000b\u0000\u0545\u016d\u0001\u0000\u0000\u0000\u0546\u0547\u0003"+ + "<\u0016\u0000\u0547\u0548\u0001\u0000\u0000\u0000\u0548\u0549\u0006\u00af"+ + "\u000b\u0000\u0549\u016f\u0001\u0000\u0000\u0000\u054a\u054b\u0003>\u0017"+ + "\u0000\u054b\u054c\u0001\u0000\u0000\u0000\u054c\u054d\u0006\u00b0\u000b"+ + "\u0000\u054d\u0171\u0001\u0000\u0000\u0000\u054e\u054f\u0003N\u001f\u0000"+ + "\u054f\u0550\u0001\u0000\u0000\u0000\u0550\u0551\u0006\u00b1\u000e\u0000"+ + "\u0551\u0552\u0006\u00b1\u000f\u0000\u0552\u0173\u0001\u0000\u0000\u0000"+ + "\u0553\u0554\u0003B\u0019\u0000\u0554\u0555\u0001\u0000\u0000\u0000\u0555"+ + "\u0556\u0006\u00b2\u0014\u0000\u0556\u0557\u0006\u00b2\u000f\u0000\u0557"+ + "\u0558\u0006\u00b2\u001f\u0000\u0558\u0175\u0001\u0000\u0000\u0000\u0559"+ + "\u055a\u0003:\u0015\u0000\u055a\u055b\u0001\u0000\u0000\u0000\u055b\u055c"+ + "\u0006\u00b3\u000b\u0000\u055c\u0177\u0001\u0000\u0000\u0000\u055d\u055e"+ + "\u0003<\u0016\u0000\u055e\u055f\u0001\u0000\u0000\u0000\u055f\u0560\u0006"+ + "\u00b4\u000b\u0000\u0560\u0179\u0001\u0000\u0000\u0000\u0561\u0562\u0003"+ + ">\u0017\u0000\u0562\u0563\u0001\u0000\u0000\u0000\u0563\u0564\u0006\u00b5"+ + "\u000b\u0000\u0564\u017b\u0001\u0000\u0000\u0000\u0565\u0566\u0003t2\u0000"+ + "\u0566\u0567\u0001\u0000\u0000\u0000\u0567\u0568\u0006\u00b6\u0011\u0000"+ + "\u0568\u0569\u0006\u00b6\u000f\u0000\u0569\u056a\u0006\u00b6\u0007\u0000"+ + "\u056a\u017d\u0001\u0000\u0000\u0000\u056b\u056c\u0003:\u0015\u0000\u056c"+ + "\u056d\u0001\u0000\u0000\u0000\u056d\u056e\u0006\u00b7\u000b\u0000\u056e"+ + "\u017f\u0001\u0000\u0000\u0000\u056f\u0570\u0003<\u0016\u0000\u0570\u0571"+ + "\u0001\u0000\u0000\u0000\u0571\u0572\u0006\u00b8\u000b\u0000\u0572\u0181"+ + "\u0001\u0000\u0000\u0000\u0573\u0574\u0003>\u0017\u0000\u0574\u0575\u0001"+ + "\u0000\u0000\u0000\u0575\u0576\u0006\u00b9\u000b\u0000\u0576\u0183\u0001"+ + "\u0000\u0000\u0000\u0577\u0578\u0003\u00baU\u0000\u0578\u0579\u0001\u0000"+ + "\u0000\u0000\u0579\u057a\u0006\u00ba\u000f\u0000\u057a\u057b\u0006\u00ba"+ + "\u0000\u0000\u057b\u057c\u0006\u00ba\u0019\u0000\u057c\u0185\u0001\u0000"+ + "\u0000\u0000\u057d\u057e\u0003\u00b6S\u0000\u057e\u057f\u0001\u0000\u0000"+ + "\u0000\u057f\u0580\u0006\u00bb\u000f\u0000\u0580\u0581\u0006\u00bb\u0000"+ + "\u0000\u0581\u0582\u0006\u00bb\u001e\u0000\u0582\u0187\u0001\u0000\u0000"+ + "\u0000\u0583\u0584\u0003j-\u0000\u0584\u0585\u0001\u0000\u0000\u0000\u0585"+ + "\u0586\u0006\u00bc\u000f\u0000\u0586\u0587\u0006\u00bc\u0000\u0000\u0587"+ + "\u0588\u0006\u00bc \u0000\u0588\u0189\u0001\u0000\u0000\u0000\u0589\u058a"+ + "\u0003N\u001f\u0000\u058a\u058b\u0001\u0000\u0000\u0000\u058b\u058c\u0006"+ + "\u00bd\u000e\u0000\u058c\u058d\u0006\u00bd\u000f\u0000\u058d\u018b\u0001"+ + "\u0000\u0000\u0000A\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b"+ + "\t\n\u000b\f\r\u000e\u000f\u0238\u0242\u0246\u0249\u0252\u0254\u025f\u0266"+ + "\u026b\u0292\u0297\u02a0\u02a7\u02ac\u02ae\u02b9\u02c1\u02c4\u02c6\u02cb"+ + "\u02d0\u02d6\u02dd\u02e2\u02e8\u02eb\u02f3\u02f7\u0373\u037a\u037c\u038c"+ + "\u0391\u0396\u0398\u039e\u03f3\u03f7\u03fc\u0401\u0406\u0408\u040c\u040e"+ + "\u045b\u045f\u0464\u053e\u0540!\u0005\u0002\u0000\u0005\u0004\u0000\u0005"+ + "\u0006\u0000\u0005\u0001\u0000\u0005\u0003\u0000\u0005\b\u0000\u0005\f"+ + "\u0000\u0005\u000e\u0000\u0005\n\u0000\u0005\u0005\u0000\u0005\u000b\u0000"+ + "\u0000\u0001\u0000\u0007E\u0000\u0005\u0000\u0000\u0007\u001d\u0000\u0004"+ + "\u0000\u0000\u0007F\u0000\u0007&\u0000\u0007$\u0000\u0007\u001e\u0000"+ + "\u0007\u0019\u0000\u0007(\u0000\u0007P\u0000\u0005\r\u0000\u0005\u0007"+ + "\u0000\u0007H\u0000\u0007Z\u0000\u0007Y\u0000\u0007X\u0000\u0005\t\u0000"+ + "\u0007G\u0000\u0005\u000f\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 76663717c5624..5900020590110 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 @@ -68,6 +68,7 @@ null '/' '%' null +null ']' null null @@ -193,6 +194,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -281,6 +283,7 @@ qualifiedNamePatterns identifier identifierPattern constant +params limitCommand sortCommand orderExpression @@ -309,4 +312,4 @@ lookupCommand atn: -[4, 1, 123, 548, 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, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 120, 8, 1, 10, 1, 12, 1, 123, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 131, 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, 1, 3, 3, 3, 147, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 159, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 166, 8, 5, 10, 5, 12, 5, 169, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 176, 8, 5, 1, 5, 1, 5, 3, 5, 180, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 188, 8, 5, 10, 5, 12, 5, 191, 9, 5, 1, 6, 1, 6, 3, 6, 195, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 202, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 207, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 214, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 220, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 228, 8, 8, 10, 8, 12, 8, 231, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 241, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 246, 8, 9, 10, 9, 12, 9, 249, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 257, 8, 10, 10, 10, 12, 10, 260, 9, 10, 3, 10, 262, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 274, 8, 13, 10, 13, 12, 13, 277, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 284, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 290, 8, 15, 10, 15, 12, 15, 293, 9, 15, 1, 15, 3, 15, 296, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 302, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 308, 8, 18, 10, 18, 12, 18, 311, 9, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 321, 8, 20, 10, 20, 12, 20, 324, 9, 20, 1, 20, 3, 20, 327, 8, 20, 1, 20, 1, 20, 3, 20, 331, 8, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 338, 8, 22, 1, 22, 1, 22, 3, 22, 342, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 348, 8, 23, 1, 24, 1, 24, 1, 24, 5, 24, 353, 8, 24, 10, 24, 12, 24, 356, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 361, 8, 25, 10, 25, 12, 25, 364, 9, 25, 1, 26, 1, 26, 1, 26, 5, 26, 369, 8, 26, 10, 26, 12, 26, 372, 9, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 391, 8, 29, 10, 29, 12, 29, 394, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 402, 8, 29, 10, 29, 12, 29, 405, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 413, 8, 29, 10, 29, 12, 29, 416, 9, 29, 1, 29, 1, 29, 3, 29, 420, 8, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 429, 8, 31, 10, 31, 12, 31, 432, 9, 31, 1, 32, 1, 32, 3, 32, 436, 8, 32, 1, 32, 1, 32, 3, 32, 440, 8, 32, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 452, 8, 35, 10, 35, 12, 35, 455, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 465, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 5, 40, 477, 8, 40, 10, 40, 12, 40, 480, 9, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 3, 43, 490, 8, 43, 1, 44, 3, 44, 493, 8, 44, 1, 44, 1, 44, 1, 45, 3, 45, 498, 8, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 3, 52, 523, 8, 52, 1, 52, 1, 52, 1, 52, 1, 52, 5, 52, 529, 8, 52, 10, 52, 12, 52, 532, 9, 52, 3, 52, 534, 8, 52, 1, 53, 1, 53, 1, 53, 3, 53, 539, 8, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 0, 4, 2, 10, 16, 18, 55, 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, 92, 94, 96, 98, 100, 102, 104, 106, 108, 0, 7, 1, 0, 63, 64, 1, 0, 65, 67, 1, 0, 70, 71, 2, 0, 35, 35, 39, 39, 1, 0, 42, 43, 2, 0, 41, 41, 55, 55, 2, 0, 56, 56, 58, 62, 574, 0, 110, 1, 0, 0, 0, 2, 113, 1, 0, 0, 0, 4, 130, 1, 0, 0, 0, 6, 146, 1, 0, 0, 0, 8, 148, 1, 0, 0, 0, 10, 179, 1, 0, 0, 0, 12, 206, 1, 0, 0, 0, 14, 213, 1, 0, 0, 0, 16, 219, 1, 0, 0, 0, 18, 240, 1, 0, 0, 0, 20, 250, 1, 0, 0, 0, 22, 265, 1, 0, 0, 0, 24, 267, 1, 0, 0, 0, 26, 270, 1, 0, 0, 0, 28, 283, 1, 0, 0, 0, 30, 285, 1, 0, 0, 0, 32, 297, 1, 0, 0, 0, 34, 301, 1, 0, 0, 0, 36, 303, 1, 0, 0, 0, 38, 312, 1, 0, 0, 0, 40, 316, 1, 0, 0, 0, 42, 332, 1, 0, 0, 0, 44, 335, 1, 0, 0, 0, 46, 343, 1, 0, 0, 0, 48, 349, 1, 0, 0, 0, 50, 357, 1, 0, 0, 0, 52, 365, 1, 0, 0, 0, 54, 373, 1, 0, 0, 0, 56, 375, 1, 0, 0, 0, 58, 419, 1, 0, 0, 0, 60, 421, 1, 0, 0, 0, 62, 424, 1, 0, 0, 0, 64, 433, 1, 0, 0, 0, 66, 441, 1, 0, 0, 0, 68, 444, 1, 0, 0, 0, 70, 447, 1, 0, 0, 0, 72, 456, 1, 0, 0, 0, 74, 460, 1, 0, 0, 0, 76, 466, 1, 0, 0, 0, 78, 470, 1, 0, 0, 0, 80, 473, 1, 0, 0, 0, 82, 481, 1, 0, 0, 0, 84, 485, 1, 0, 0, 0, 86, 489, 1, 0, 0, 0, 88, 492, 1, 0, 0, 0, 90, 497, 1, 0, 0, 0, 92, 501, 1, 0, 0, 0, 94, 503, 1, 0, 0, 0, 96, 505, 1, 0, 0, 0, 98, 508, 1, 0, 0, 0, 100, 512, 1, 0, 0, 0, 102, 515, 1, 0, 0, 0, 104, 518, 1, 0, 0, 0, 106, 538, 1, 0, 0, 0, 108, 542, 1, 0, 0, 0, 110, 111, 3, 2, 1, 0, 111, 112, 5, 0, 0, 1, 112, 1, 1, 0, 0, 0, 113, 114, 6, 1, -1, 0, 114, 115, 3, 4, 2, 0, 115, 121, 1, 0, 0, 0, 116, 117, 10, 1, 0, 0, 117, 118, 5, 29, 0, 0, 118, 120, 3, 6, 3, 0, 119, 116, 1, 0, 0, 0, 120, 123, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 3, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 124, 131, 3, 96, 48, 0, 125, 131, 3, 30, 15, 0, 126, 131, 3, 24, 12, 0, 127, 131, 3, 40, 20, 0, 128, 131, 3, 100, 50, 0, 129, 131, 3, 102, 51, 0, 130, 124, 1, 0, 0, 0, 130, 125, 1, 0, 0, 0, 130, 126, 1, 0, 0, 0, 130, 127, 1, 0, 0, 0, 130, 128, 1, 0, 0, 0, 130, 129, 1, 0, 0, 0, 131, 5, 1, 0, 0, 0, 132, 147, 3, 42, 21, 0, 133, 147, 3, 46, 23, 0, 134, 147, 3, 60, 30, 0, 135, 147, 3, 108, 54, 0, 136, 147, 3, 66, 33, 0, 137, 147, 3, 62, 31, 0, 138, 147, 3, 44, 22, 0, 139, 147, 3, 8, 4, 0, 140, 147, 3, 68, 34, 0, 141, 147, 3, 70, 35, 0, 142, 147, 3, 74, 37, 0, 143, 147, 3, 76, 38, 0, 144, 147, 3, 104, 52, 0, 145, 147, 3, 78, 39, 0, 146, 132, 1, 0, 0, 0, 146, 133, 1, 0, 0, 0, 146, 134, 1, 0, 0, 0, 146, 135, 1, 0, 0, 0, 146, 136, 1, 0, 0, 0, 146, 137, 1, 0, 0, 0, 146, 138, 1, 0, 0, 0, 146, 139, 1, 0, 0, 0, 146, 140, 1, 0, 0, 0, 146, 141, 1, 0, 0, 0, 146, 142, 1, 0, 0, 0, 146, 143, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 146, 145, 1, 0, 0, 0, 147, 7, 1, 0, 0, 0, 148, 149, 5, 20, 0, 0, 149, 150, 3, 10, 5, 0, 150, 9, 1, 0, 0, 0, 151, 152, 6, 5, -1, 0, 152, 153, 5, 48, 0, 0, 153, 180, 3, 10, 5, 7, 154, 180, 3, 14, 7, 0, 155, 180, 3, 12, 6, 0, 156, 158, 3, 14, 7, 0, 157, 159, 5, 48, 0, 0, 158, 157, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 161, 5, 45, 0, 0, 161, 162, 5, 44, 0, 0, 162, 167, 3, 14, 7, 0, 163, 164, 5, 38, 0, 0, 164, 166, 3, 14, 7, 0, 165, 163, 1, 0, 0, 0, 166, 169, 1, 0, 0, 0, 167, 165, 1, 0, 0, 0, 167, 168, 1, 0, 0, 0, 168, 170, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 170, 171, 5, 54, 0, 0, 171, 180, 1, 0, 0, 0, 172, 173, 3, 14, 7, 0, 173, 175, 5, 46, 0, 0, 174, 176, 5, 48, 0, 0, 175, 174, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 178, 5, 49, 0, 0, 178, 180, 1, 0, 0, 0, 179, 151, 1, 0, 0, 0, 179, 154, 1, 0, 0, 0, 179, 155, 1, 0, 0, 0, 179, 156, 1, 0, 0, 0, 179, 172, 1, 0, 0, 0, 180, 189, 1, 0, 0, 0, 181, 182, 10, 4, 0, 0, 182, 183, 5, 34, 0, 0, 183, 188, 3, 10, 5, 5, 184, 185, 10, 3, 0, 0, 185, 186, 5, 51, 0, 0, 186, 188, 3, 10, 5, 4, 187, 181, 1, 0, 0, 0, 187, 184, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 11, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 194, 3, 14, 7, 0, 193, 195, 5, 48, 0, 0, 194, 193, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 197, 5, 47, 0, 0, 197, 198, 3, 92, 46, 0, 198, 207, 1, 0, 0, 0, 199, 201, 3, 14, 7, 0, 200, 202, 5, 48, 0, 0, 201, 200, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 204, 5, 53, 0, 0, 204, 205, 3, 92, 46, 0, 205, 207, 1, 0, 0, 0, 206, 192, 1, 0, 0, 0, 206, 199, 1, 0, 0, 0, 207, 13, 1, 0, 0, 0, 208, 214, 3, 16, 8, 0, 209, 210, 3, 16, 8, 0, 210, 211, 3, 94, 47, 0, 211, 212, 3, 16, 8, 0, 212, 214, 1, 0, 0, 0, 213, 208, 1, 0, 0, 0, 213, 209, 1, 0, 0, 0, 214, 15, 1, 0, 0, 0, 215, 216, 6, 8, -1, 0, 216, 220, 3, 18, 9, 0, 217, 218, 7, 0, 0, 0, 218, 220, 3, 16, 8, 3, 219, 215, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 220, 229, 1, 0, 0, 0, 221, 222, 10, 2, 0, 0, 222, 223, 7, 1, 0, 0, 223, 228, 3, 16, 8, 3, 224, 225, 10, 1, 0, 0, 225, 226, 7, 0, 0, 0, 226, 228, 3, 16, 8, 2, 227, 221, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 231, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 17, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 232, 233, 6, 9, -1, 0, 233, 241, 3, 58, 29, 0, 234, 241, 3, 48, 24, 0, 235, 241, 3, 20, 10, 0, 236, 237, 5, 44, 0, 0, 237, 238, 3, 10, 5, 0, 238, 239, 5, 54, 0, 0, 239, 241, 1, 0, 0, 0, 240, 232, 1, 0, 0, 0, 240, 234, 1, 0, 0, 0, 240, 235, 1, 0, 0, 0, 240, 236, 1, 0, 0, 0, 241, 247, 1, 0, 0, 0, 242, 243, 10, 1, 0, 0, 243, 244, 5, 37, 0, 0, 244, 246, 3, 22, 11, 0, 245, 242, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 19, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, 3, 54, 27, 0, 251, 261, 5, 44, 0, 0, 252, 262, 5, 65, 0, 0, 253, 258, 3, 10, 5, 0, 254, 255, 5, 38, 0, 0, 255, 257, 3, 10, 5, 0, 256, 254, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 262, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 252, 1, 0, 0, 0, 261, 253, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 264, 5, 54, 0, 0, 264, 21, 1, 0, 0, 0, 265, 266, 3, 54, 27, 0, 266, 23, 1, 0, 0, 0, 267, 268, 5, 16, 0, 0, 268, 269, 3, 26, 13, 0, 269, 25, 1, 0, 0, 0, 270, 275, 3, 28, 14, 0, 271, 272, 5, 38, 0, 0, 272, 274, 3, 28, 14, 0, 273, 271, 1, 0, 0, 0, 274, 277, 1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 27, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 284, 3, 10, 5, 0, 279, 280, 3, 48, 24, 0, 280, 281, 5, 36, 0, 0, 281, 282, 3, 10, 5, 0, 282, 284, 1, 0, 0, 0, 283, 278, 1, 0, 0, 0, 283, 279, 1, 0, 0, 0, 284, 29, 1, 0, 0, 0, 285, 286, 5, 6, 0, 0, 286, 291, 3, 32, 16, 0, 287, 288, 5, 38, 0, 0, 288, 290, 3, 32, 16, 0, 289, 287, 1, 0, 0, 0, 290, 293, 1, 0, 0, 0, 291, 289, 1, 0, 0, 0, 291, 292, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 294, 296, 3, 34, 17, 0, 295, 294, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 31, 1, 0, 0, 0, 297, 298, 5, 25, 0, 0, 298, 33, 1, 0, 0, 0, 299, 302, 3, 36, 18, 0, 300, 302, 3, 38, 19, 0, 301, 299, 1, 0, 0, 0, 301, 300, 1, 0, 0, 0, 302, 35, 1, 0, 0, 0, 303, 304, 5, 75, 0, 0, 304, 309, 3, 32, 16, 0, 305, 306, 5, 38, 0, 0, 306, 308, 3, 32, 16, 0, 307, 305, 1, 0, 0, 0, 308, 311, 1, 0, 0, 0, 309, 307, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 37, 1, 0, 0, 0, 311, 309, 1, 0, 0, 0, 312, 313, 5, 68, 0, 0, 313, 314, 3, 36, 18, 0, 314, 315, 5, 69, 0, 0, 315, 39, 1, 0, 0, 0, 316, 317, 5, 13, 0, 0, 317, 322, 3, 32, 16, 0, 318, 319, 5, 38, 0, 0, 319, 321, 3, 32, 16, 0, 320, 318, 1, 0, 0, 0, 321, 324, 1, 0, 0, 0, 322, 320, 1, 0, 0, 0, 322, 323, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 325, 327, 3, 26, 13, 0, 326, 325, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 329, 5, 33, 0, 0, 329, 331, 3, 26, 13, 0, 330, 328, 1, 0, 0, 0, 330, 331, 1, 0, 0, 0, 331, 41, 1, 0, 0, 0, 332, 333, 5, 4, 0, 0, 333, 334, 3, 26, 13, 0, 334, 43, 1, 0, 0, 0, 335, 337, 5, 19, 0, 0, 336, 338, 3, 26, 13, 0, 337, 336, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 341, 1, 0, 0, 0, 339, 340, 5, 33, 0, 0, 340, 342, 3, 26, 13, 0, 341, 339, 1, 0, 0, 0, 341, 342, 1, 0, 0, 0, 342, 45, 1, 0, 0, 0, 343, 344, 5, 8, 0, 0, 344, 347, 3, 26, 13, 0, 345, 346, 5, 33, 0, 0, 346, 348, 3, 26, 13, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 47, 1, 0, 0, 0, 349, 354, 3, 54, 27, 0, 350, 351, 5, 40, 0, 0, 351, 353, 3, 54, 27, 0, 352, 350, 1, 0, 0, 0, 353, 356, 1, 0, 0, 0, 354, 352, 1, 0, 0, 0, 354, 355, 1, 0, 0, 0, 355, 49, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 357, 362, 3, 56, 28, 0, 358, 359, 5, 40, 0, 0, 359, 361, 3, 56, 28, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 51, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 370, 3, 50, 25, 0, 366, 367, 5, 38, 0, 0, 367, 369, 3, 50, 25, 0, 368, 366, 1, 0, 0, 0, 369, 372, 1, 0, 0, 0, 370, 368, 1, 0, 0, 0, 370, 371, 1, 0, 0, 0, 371, 53, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 373, 374, 7, 2, 0, 0, 374, 55, 1, 0, 0, 0, 375, 376, 5, 79, 0, 0, 376, 57, 1, 0, 0, 0, 377, 420, 5, 49, 0, 0, 378, 379, 3, 90, 45, 0, 379, 380, 5, 70, 0, 0, 380, 420, 1, 0, 0, 0, 381, 420, 3, 88, 44, 0, 382, 420, 3, 90, 45, 0, 383, 420, 3, 84, 42, 0, 384, 420, 5, 52, 0, 0, 385, 420, 3, 92, 46, 0, 386, 387, 5, 68, 0, 0, 387, 392, 3, 86, 43, 0, 388, 389, 5, 38, 0, 0, 389, 391, 3, 86, 43, 0, 390, 388, 1, 0, 0, 0, 391, 394, 1, 0, 0, 0, 392, 390, 1, 0, 0, 0, 392, 393, 1, 0, 0, 0, 393, 395, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 395, 396, 5, 69, 0, 0, 396, 420, 1, 0, 0, 0, 397, 398, 5, 68, 0, 0, 398, 403, 3, 84, 42, 0, 399, 400, 5, 38, 0, 0, 400, 402, 3, 84, 42, 0, 401, 399, 1, 0, 0, 0, 402, 405, 1, 0, 0, 0, 403, 401, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 406, 1, 0, 0, 0, 405, 403, 1, 0, 0, 0, 406, 407, 5, 69, 0, 0, 407, 420, 1, 0, 0, 0, 408, 409, 5, 68, 0, 0, 409, 414, 3, 92, 46, 0, 410, 411, 5, 38, 0, 0, 411, 413, 3, 92, 46, 0, 412, 410, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 414, 415, 1, 0, 0, 0, 415, 417, 1, 0, 0, 0, 416, 414, 1, 0, 0, 0, 417, 418, 5, 69, 0, 0, 418, 420, 1, 0, 0, 0, 419, 377, 1, 0, 0, 0, 419, 378, 1, 0, 0, 0, 419, 381, 1, 0, 0, 0, 419, 382, 1, 0, 0, 0, 419, 383, 1, 0, 0, 0, 419, 384, 1, 0, 0, 0, 419, 385, 1, 0, 0, 0, 419, 386, 1, 0, 0, 0, 419, 397, 1, 0, 0, 0, 419, 408, 1, 0, 0, 0, 420, 59, 1, 0, 0, 0, 421, 422, 5, 10, 0, 0, 422, 423, 5, 31, 0, 0, 423, 61, 1, 0, 0, 0, 424, 425, 5, 18, 0, 0, 425, 430, 3, 64, 32, 0, 426, 427, 5, 38, 0, 0, 427, 429, 3, 64, 32, 0, 428, 426, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 63, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 433, 435, 3, 10, 5, 0, 434, 436, 7, 3, 0, 0, 435, 434, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 439, 1, 0, 0, 0, 437, 438, 5, 50, 0, 0, 438, 440, 7, 4, 0, 0, 439, 437, 1, 0, 0, 0, 439, 440, 1, 0, 0, 0, 440, 65, 1, 0, 0, 0, 441, 442, 5, 9, 0, 0, 442, 443, 3, 52, 26, 0, 443, 67, 1, 0, 0, 0, 444, 445, 5, 2, 0, 0, 445, 446, 3, 52, 26, 0, 446, 69, 1, 0, 0, 0, 447, 448, 5, 15, 0, 0, 448, 453, 3, 72, 36, 0, 449, 450, 5, 38, 0, 0, 450, 452, 3, 72, 36, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 71, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 457, 3, 50, 25, 0, 457, 458, 5, 83, 0, 0, 458, 459, 3, 50, 25, 0, 459, 73, 1, 0, 0, 0, 460, 461, 5, 1, 0, 0, 461, 462, 3, 18, 9, 0, 462, 464, 3, 92, 46, 0, 463, 465, 3, 80, 40, 0, 464, 463, 1, 0, 0, 0, 464, 465, 1, 0, 0, 0, 465, 75, 1, 0, 0, 0, 466, 467, 5, 7, 0, 0, 467, 468, 3, 18, 9, 0, 468, 469, 3, 92, 46, 0, 469, 77, 1, 0, 0, 0, 470, 471, 5, 14, 0, 0, 471, 472, 3, 48, 24, 0, 472, 79, 1, 0, 0, 0, 473, 478, 3, 82, 41, 0, 474, 475, 5, 38, 0, 0, 475, 477, 3, 82, 41, 0, 476, 474, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 81, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 482, 3, 54, 27, 0, 482, 483, 5, 36, 0, 0, 483, 484, 3, 58, 29, 0, 484, 83, 1, 0, 0, 0, 485, 486, 7, 5, 0, 0, 486, 85, 1, 0, 0, 0, 487, 490, 3, 88, 44, 0, 488, 490, 3, 90, 45, 0, 489, 487, 1, 0, 0, 0, 489, 488, 1, 0, 0, 0, 490, 87, 1, 0, 0, 0, 491, 493, 7, 0, 0, 0, 492, 491, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 495, 5, 32, 0, 0, 495, 89, 1, 0, 0, 0, 496, 498, 7, 0, 0, 0, 497, 496, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 5, 31, 0, 0, 500, 91, 1, 0, 0, 0, 501, 502, 5, 30, 0, 0, 502, 93, 1, 0, 0, 0, 503, 504, 7, 6, 0, 0, 504, 95, 1, 0, 0, 0, 505, 506, 5, 5, 0, 0, 506, 507, 3, 98, 49, 0, 507, 97, 1, 0, 0, 0, 508, 509, 5, 68, 0, 0, 509, 510, 3, 2, 1, 0, 510, 511, 5, 69, 0, 0, 511, 99, 1, 0, 0, 0, 512, 513, 5, 17, 0, 0, 513, 514, 5, 105, 0, 0, 514, 101, 1, 0, 0, 0, 515, 516, 5, 12, 0, 0, 516, 517, 5, 109, 0, 0, 517, 103, 1, 0, 0, 0, 518, 519, 5, 3, 0, 0, 519, 522, 5, 89, 0, 0, 520, 521, 5, 87, 0, 0, 521, 523, 3, 50, 25, 0, 522, 520, 1, 0, 0, 0, 522, 523, 1, 0, 0, 0, 523, 533, 1, 0, 0, 0, 524, 525, 5, 88, 0, 0, 525, 530, 3, 106, 53, 0, 526, 527, 5, 38, 0, 0, 527, 529, 3, 106, 53, 0, 528, 526, 1, 0, 0, 0, 529, 532, 1, 0, 0, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 534, 1, 0, 0, 0, 532, 530, 1, 0, 0, 0, 533, 524, 1, 0, 0, 0, 533, 534, 1, 0, 0, 0, 534, 105, 1, 0, 0, 0, 535, 536, 3, 50, 25, 0, 536, 537, 5, 36, 0, 0, 537, 539, 1, 0, 0, 0, 538, 535, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 541, 3, 50, 25, 0, 541, 107, 1, 0, 0, 0, 542, 543, 5, 11, 0, 0, 543, 544, 5, 25, 0, 0, 544, 545, 5, 87, 0, 0, 545, 546, 3, 52, 26, 0, 546, 109, 1, 0, 0, 0, 52, 121, 130, 146, 158, 167, 175, 179, 187, 189, 194, 201, 206, 213, 219, 227, 229, 240, 247, 258, 261, 275, 283, 291, 295, 301, 309, 322, 326, 330, 337, 341, 347, 354, 362, 370, 392, 403, 414, 419, 430, 435, 439, 453, 464, 478, 489, 492, 497, 522, 530, 533, 538] \ No newline at end of file +[4, 1, 124, 554, 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, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 122, 8, 1, 10, 1, 12, 1, 125, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 133, 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, 1, 3, 3, 3, 149, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 161, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 168, 8, 5, 10, 5, 12, 5, 171, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 178, 8, 5, 1, 5, 1, 5, 3, 5, 182, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 190, 8, 5, 10, 5, 12, 5, 193, 9, 5, 1, 6, 1, 6, 3, 6, 197, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 204, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 209, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 216, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 222, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 230, 8, 8, 10, 8, 12, 8, 233, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 243, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 248, 8, 9, 10, 9, 12, 9, 251, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 259, 8, 10, 10, 10, 12, 10, 262, 9, 10, 3, 10, 264, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 276, 8, 13, 10, 13, 12, 13, 279, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 286, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 292, 8, 15, 10, 15, 12, 15, 295, 9, 15, 1, 15, 3, 15, 298, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 304, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 310, 8, 18, 10, 18, 12, 18, 313, 9, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 323, 8, 20, 10, 20, 12, 20, 326, 9, 20, 1, 20, 3, 20, 329, 8, 20, 1, 20, 1, 20, 3, 20, 333, 8, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 340, 8, 22, 1, 22, 1, 22, 3, 22, 344, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 350, 8, 23, 1, 24, 1, 24, 1, 24, 5, 24, 355, 8, 24, 10, 24, 12, 24, 358, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 363, 8, 25, 10, 25, 12, 25, 366, 9, 25, 1, 26, 1, 26, 1, 26, 5, 26, 371, 8, 26, 10, 26, 12, 26, 374, 9, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 393, 8, 29, 10, 29, 12, 29, 396, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 404, 8, 29, 10, 29, 12, 29, 407, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 415, 8, 29, 10, 29, 12, 29, 418, 9, 29, 1, 29, 1, 29, 3, 29, 422, 8, 29, 1, 30, 1, 30, 3, 30, 426, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 435, 8, 32, 10, 32, 12, 32, 438, 9, 32, 1, 33, 1, 33, 3, 33, 442, 8, 33, 1, 33, 1, 33, 3, 33, 446, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 458, 8, 36, 10, 36, 12, 36, 461, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 471, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 483, 8, 41, 10, 41, 12, 41, 486, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 44, 1, 44, 3, 44, 496, 8, 44, 1, 45, 3, 45, 499, 8, 45, 1, 45, 1, 45, 1, 46, 3, 46, 504, 8, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 3, 53, 529, 8, 53, 1, 53, 1, 53, 1, 53, 1, 53, 5, 53, 535, 8, 53, 10, 53, 12, 53, 538, 9, 53, 3, 53, 540, 8, 53, 1, 54, 1, 54, 1, 54, 3, 54, 545, 8, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 0, 4, 2, 10, 16, 18, 56, 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, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 0, 7, 1, 0, 63, 64, 1, 0, 65, 67, 1, 0, 71, 72, 2, 0, 35, 35, 39, 39, 1, 0, 42, 43, 2, 0, 41, 41, 55, 55, 2, 0, 56, 56, 58, 62, 580, 0, 112, 1, 0, 0, 0, 2, 115, 1, 0, 0, 0, 4, 132, 1, 0, 0, 0, 6, 148, 1, 0, 0, 0, 8, 150, 1, 0, 0, 0, 10, 181, 1, 0, 0, 0, 12, 208, 1, 0, 0, 0, 14, 215, 1, 0, 0, 0, 16, 221, 1, 0, 0, 0, 18, 242, 1, 0, 0, 0, 20, 252, 1, 0, 0, 0, 22, 267, 1, 0, 0, 0, 24, 269, 1, 0, 0, 0, 26, 272, 1, 0, 0, 0, 28, 285, 1, 0, 0, 0, 30, 287, 1, 0, 0, 0, 32, 299, 1, 0, 0, 0, 34, 303, 1, 0, 0, 0, 36, 305, 1, 0, 0, 0, 38, 314, 1, 0, 0, 0, 40, 318, 1, 0, 0, 0, 42, 334, 1, 0, 0, 0, 44, 337, 1, 0, 0, 0, 46, 345, 1, 0, 0, 0, 48, 351, 1, 0, 0, 0, 50, 359, 1, 0, 0, 0, 52, 367, 1, 0, 0, 0, 54, 375, 1, 0, 0, 0, 56, 377, 1, 0, 0, 0, 58, 421, 1, 0, 0, 0, 60, 425, 1, 0, 0, 0, 62, 427, 1, 0, 0, 0, 64, 430, 1, 0, 0, 0, 66, 439, 1, 0, 0, 0, 68, 447, 1, 0, 0, 0, 70, 450, 1, 0, 0, 0, 72, 453, 1, 0, 0, 0, 74, 462, 1, 0, 0, 0, 76, 466, 1, 0, 0, 0, 78, 472, 1, 0, 0, 0, 80, 476, 1, 0, 0, 0, 82, 479, 1, 0, 0, 0, 84, 487, 1, 0, 0, 0, 86, 491, 1, 0, 0, 0, 88, 495, 1, 0, 0, 0, 90, 498, 1, 0, 0, 0, 92, 503, 1, 0, 0, 0, 94, 507, 1, 0, 0, 0, 96, 509, 1, 0, 0, 0, 98, 511, 1, 0, 0, 0, 100, 514, 1, 0, 0, 0, 102, 518, 1, 0, 0, 0, 104, 521, 1, 0, 0, 0, 106, 524, 1, 0, 0, 0, 108, 544, 1, 0, 0, 0, 110, 548, 1, 0, 0, 0, 112, 113, 3, 2, 1, 0, 113, 114, 5, 0, 0, 1, 114, 1, 1, 0, 0, 0, 115, 116, 6, 1, -1, 0, 116, 117, 3, 4, 2, 0, 117, 123, 1, 0, 0, 0, 118, 119, 10, 1, 0, 0, 119, 120, 5, 29, 0, 0, 120, 122, 3, 6, 3, 0, 121, 118, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 3, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 133, 3, 98, 49, 0, 127, 133, 3, 30, 15, 0, 128, 133, 3, 24, 12, 0, 129, 133, 3, 40, 20, 0, 130, 133, 3, 102, 51, 0, 131, 133, 3, 104, 52, 0, 132, 126, 1, 0, 0, 0, 132, 127, 1, 0, 0, 0, 132, 128, 1, 0, 0, 0, 132, 129, 1, 0, 0, 0, 132, 130, 1, 0, 0, 0, 132, 131, 1, 0, 0, 0, 133, 5, 1, 0, 0, 0, 134, 149, 3, 42, 21, 0, 135, 149, 3, 46, 23, 0, 136, 149, 3, 62, 31, 0, 137, 149, 3, 110, 55, 0, 138, 149, 3, 68, 34, 0, 139, 149, 3, 64, 32, 0, 140, 149, 3, 44, 22, 0, 141, 149, 3, 8, 4, 0, 142, 149, 3, 70, 35, 0, 143, 149, 3, 72, 36, 0, 144, 149, 3, 76, 38, 0, 145, 149, 3, 78, 39, 0, 146, 149, 3, 106, 53, 0, 147, 149, 3, 80, 40, 0, 148, 134, 1, 0, 0, 0, 148, 135, 1, 0, 0, 0, 148, 136, 1, 0, 0, 0, 148, 137, 1, 0, 0, 0, 148, 138, 1, 0, 0, 0, 148, 139, 1, 0, 0, 0, 148, 140, 1, 0, 0, 0, 148, 141, 1, 0, 0, 0, 148, 142, 1, 0, 0, 0, 148, 143, 1, 0, 0, 0, 148, 144, 1, 0, 0, 0, 148, 145, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 147, 1, 0, 0, 0, 149, 7, 1, 0, 0, 0, 150, 151, 5, 20, 0, 0, 151, 152, 3, 10, 5, 0, 152, 9, 1, 0, 0, 0, 153, 154, 6, 5, -1, 0, 154, 155, 5, 48, 0, 0, 155, 182, 3, 10, 5, 7, 156, 182, 3, 14, 7, 0, 157, 182, 3, 12, 6, 0, 158, 160, 3, 14, 7, 0, 159, 161, 5, 48, 0, 0, 160, 159, 1, 0, 0, 0, 160, 161, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 5, 45, 0, 0, 163, 164, 5, 44, 0, 0, 164, 169, 3, 14, 7, 0, 165, 166, 5, 38, 0, 0, 166, 168, 3, 14, 7, 0, 167, 165, 1, 0, 0, 0, 168, 171, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 172, 1, 0, 0, 0, 171, 169, 1, 0, 0, 0, 172, 173, 5, 54, 0, 0, 173, 182, 1, 0, 0, 0, 174, 175, 3, 14, 7, 0, 175, 177, 5, 46, 0, 0, 176, 178, 5, 48, 0, 0, 177, 176, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 180, 5, 49, 0, 0, 180, 182, 1, 0, 0, 0, 181, 153, 1, 0, 0, 0, 181, 156, 1, 0, 0, 0, 181, 157, 1, 0, 0, 0, 181, 158, 1, 0, 0, 0, 181, 174, 1, 0, 0, 0, 182, 191, 1, 0, 0, 0, 183, 184, 10, 4, 0, 0, 184, 185, 5, 34, 0, 0, 185, 190, 3, 10, 5, 5, 186, 187, 10, 3, 0, 0, 187, 188, 5, 51, 0, 0, 188, 190, 3, 10, 5, 4, 189, 183, 1, 0, 0, 0, 189, 186, 1, 0, 0, 0, 190, 193, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 11, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 194, 196, 3, 14, 7, 0, 195, 197, 5, 48, 0, 0, 196, 195, 1, 0, 0, 0, 196, 197, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 5, 47, 0, 0, 199, 200, 3, 94, 47, 0, 200, 209, 1, 0, 0, 0, 201, 203, 3, 14, 7, 0, 202, 204, 5, 48, 0, 0, 203, 202, 1, 0, 0, 0, 203, 204, 1, 0, 0, 0, 204, 205, 1, 0, 0, 0, 205, 206, 5, 53, 0, 0, 206, 207, 3, 94, 47, 0, 207, 209, 1, 0, 0, 0, 208, 194, 1, 0, 0, 0, 208, 201, 1, 0, 0, 0, 209, 13, 1, 0, 0, 0, 210, 216, 3, 16, 8, 0, 211, 212, 3, 16, 8, 0, 212, 213, 3, 96, 48, 0, 213, 214, 3, 16, 8, 0, 214, 216, 1, 0, 0, 0, 215, 210, 1, 0, 0, 0, 215, 211, 1, 0, 0, 0, 216, 15, 1, 0, 0, 0, 217, 218, 6, 8, -1, 0, 218, 222, 3, 18, 9, 0, 219, 220, 7, 0, 0, 0, 220, 222, 3, 16, 8, 3, 221, 217, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 222, 231, 1, 0, 0, 0, 223, 224, 10, 2, 0, 0, 224, 225, 7, 1, 0, 0, 225, 230, 3, 16, 8, 3, 226, 227, 10, 1, 0, 0, 227, 228, 7, 0, 0, 0, 228, 230, 3, 16, 8, 2, 229, 223, 1, 0, 0, 0, 229, 226, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 17, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 235, 6, 9, -1, 0, 235, 243, 3, 58, 29, 0, 236, 243, 3, 48, 24, 0, 237, 243, 3, 20, 10, 0, 238, 239, 5, 44, 0, 0, 239, 240, 3, 10, 5, 0, 240, 241, 5, 54, 0, 0, 241, 243, 1, 0, 0, 0, 242, 234, 1, 0, 0, 0, 242, 236, 1, 0, 0, 0, 242, 237, 1, 0, 0, 0, 242, 238, 1, 0, 0, 0, 243, 249, 1, 0, 0, 0, 244, 245, 10, 1, 0, 0, 245, 246, 5, 37, 0, 0, 246, 248, 3, 22, 11, 0, 247, 244, 1, 0, 0, 0, 248, 251, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 19, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 252, 253, 3, 54, 27, 0, 253, 263, 5, 44, 0, 0, 254, 264, 5, 65, 0, 0, 255, 260, 3, 10, 5, 0, 256, 257, 5, 38, 0, 0, 257, 259, 3, 10, 5, 0, 258, 256, 1, 0, 0, 0, 259, 262, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 264, 1, 0, 0, 0, 262, 260, 1, 0, 0, 0, 263, 254, 1, 0, 0, 0, 263, 255, 1, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 266, 5, 54, 0, 0, 266, 21, 1, 0, 0, 0, 267, 268, 3, 54, 27, 0, 268, 23, 1, 0, 0, 0, 269, 270, 5, 16, 0, 0, 270, 271, 3, 26, 13, 0, 271, 25, 1, 0, 0, 0, 272, 277, 3, 28, 14, 0, 273, 274, 5, 38, 0, 0, 274, 276, 3, 28, 14, 0, 275, 273, 1, 0, 0, 0, 276, 279, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 27, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 280, 286, 3, 10, 5, 0, 281, 282, 3, 48, 24, 0, 282, 283, 5, 36, 0, 0, 283, 284, 3, 10, 5, 0, 284, 286, 1, 0, 0, 0, 285, 280, 1, 0, 0, 0, 285, 281, 1, 0, 0, 0, 286, 29, 1, 0, 0, 0, 287, 288, 5, 6, 0, 0, 288, 293, 3, 32, 16, 0, 289, 290, 5, 38, 0, 0, 290, 292, 3, 32, 16, 0, 291, 289, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 296, 298, 3, 34, 17, 0, 297, 296, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 31, 1, 0, 0, 0, 299, 300, 5, 25, 0, 0, 300, 33, 1, 0, 0, 0, 301, 304, 3, 36, 18, 0, 302, 304, 3, 38, 19, 0, 303, 301, 1, 0, 0, 0, 303, 302, 1, 0, 0, 0, 304, 35, 1, 0, 0, 0, 305, 306, 5, 76, 0, 0, 306, 311, 3, 32, 16, 0, 307, 308, 5, 38, 0, 0, 308, 310, 3, 32, 16, 0, 309, 307, 1, 0, 0, 0, 310, 313, 1, 0, 0, 0, 311, 309, 1, 0, 0, 0, 311, 312, 1, 0, 0, 0, 312, 37, 1, 0, 0, 0, 313, 311, 1, 0, 0, 0, 314, 315, 5, 69, 0, 0, 315, 316, 3, 36, 18, 0, 316, 317, 5, 70, 0, 0, 317, 39, 1, 0, 0, 0, 318, 319, 5, 13, 0, 0, 319, 324, 3, 32, 16, 0, 320, 321, 5, 38, 0, 0, 321, 323, 3, 32, 16, 0, 322, 320, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 328, 1, 0, 0, 0, 326, 324, 1, 0, 0, 0, 327, 329, 3, 26, 13, 0, 328, 327, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 332, 1, 0, 0, 0, 330, 331, 5, 33, 0, 0, 331, 333, 3, 26, 13, 0, 332, 330, 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 41, 1, 0, 0, 0, 334, 335, 5, 4, 0, 0, 335, 336, 3, 26, 13, 0, 336, 43, 1, 0, 0, 0, 337, 339, 5, 19, 0, 0, 338, 340, 3, 26, 13, 0, 339, 338, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 343, 1, 0, 0, 0, 341, 342, 5, 33, 0, 0, 342, 344, 3, 26, 13, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 45, 1, 0, 0, 0, 345, 346, 5, 8, 0, 0, 346, 349, 3, 26, 13, 0, 347, 348, 5, 33, 0, 0, 348, 350, 3, 26, 13, 0, 349, 347, 1, 0, 0, 0, 349, 350, 1, 0, 0, 0, 350, 47, 1, 0, 0, 0, 351, 356, 3, 54, 27, 0, 352, 353, 5, 40, 0, 0, 353, 355, 3, 54, 27, 0, 354, 352, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 49, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 359, 364, 3, 56, 28, 0, 360, 361, 5, 40, 0, 0, 361, 363, 3, 56, 28, 0, 362, 360, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 364, 365, 1, 0, 0, 0, 365, 51, 1, 0, 0, 0, 366, 364, 1, 0, 0, 0, 367, 372, 3, 50, 25, 0, 368, 369, 5, 38, 0, 0, 369, 371, 3, 50, 25, 0, 370, 368, 1, 0, 0, 0, 371, 374, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 373, 53, 1, 0, 0, 0, 374, 372, 1, 0, 0, 0, 375, 376, 7, 2, 0, 0, 376, 55, 1, 0, 0, 0, 377, 378, 5, 80, 0, 0, 378, 57, 1, 0, 0, 0, 379, 422, 5, 49, 0, 0, 380, 381, 3, 92, 46, 0, 381, 382, 5, 71, 0, 0, 382, 422, 1, 0, 0, 0, 383, 422, 3, 90, 45, 0, 384, 422, 3, 92, 46, 0, 385, 422, 3, 86, 43, 0, 386, 422, 3, 60, 30, 0, 387, 422, 3, 94, 47, 0, 388, 389, 5, 69, 0, 0, 389, 394, 3, 88, 44, 0, 390, 391, 5, 38, 0, 0, 391, 393, 3, 88, 44, 0, 392, 390, 1, 0, 0, 0, 393, 396, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 397, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 397, 398, 5, 70, 0, 0, 398, 422, 1, 0, 0, 0, 399, 400, 5, 69, 0, 0, 400, 405, 3, 86, 43, 0, 401, 402, 5, 38, 0, 0, 402, 404, 3, 86, 43, 0, 403, 401, 1, 0, 0, 0, 404, 407, 1, 0, 0, 0, 405, 403, 1, 0, 0, 0, 405, 406, 1, 0, 0, 0, 406, 408, 1, 0, 0, 0, 407, 405, 1, 0, 0, 0, 408, 409, 5, 70, 0, 0, 409, 422, 1, 0, 0, 0, 410, 411, 5, 69, 0, 0, 411, 416, 3, 94, 47, 0, 412, 413, 5, 38, 0, 0, 413, 415, 3, 94, 47, 0, 414, 412, 1, 0, 0, 0, 415, 418, 1, 0, 0, 0, 416, 414, 1, 0, 0, 0, 416, 417, 1, 0, 0, 0, 417, 419, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 419, 420, 5, 70, 0, 0, 420, 422, 1, 0, 0, 0, 421, 379, 1, 0, 0, 0, 421, 380, 1, 0, 0, 0, 421, 383, 1, 0, 0, 0, 421, 384, 1, 0, 0, 0, 421, 385, 1, 0, 0, 0, 421, 386, 1, 0, 0, 0, 421, 387, 1, 0, 0, 0, 421, 388, 1, 0, 0, 0, 421, 399, 1, 0, 0, 0, 421, 410, 1, 0, 0, 0, 422, 59, 1, 0, 0, 0, 423, 426, 5, 52, 0, 0, 424, 426, 5, 68, 0, 0, 425, 423, 1, 0, 0, 0, 425, 424, 1, 0, 0, 0, 426, 61, 1, 0, 0, 0, 427, 428, 5, 10, 0, 0, 428, 429, 5, 31, 0, 0, 429, 63, 1, 0, 0, 0, 430, 431, 5, 18, 0, 0, 431, 436, 3, 66, 33, 0, 432, 433, 5, 38, 0, 0, 433, 435, 3, 66, 33, 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, 65, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 439, 441, 3, 10, 5, 0, 440, 442, 7, 3, 0, 0, 441, 440, 1, 0, 0, 0, 441, 442, 1, 0, 0, 0, 442, 445, 1, 0, 0, 0, 443, 444, 5, 50, 0, 0, 444, 446, 7, 4, 0, 0, 445, 443, 1, 0, 0, 0, 445, 446, 1, 0, 0, 0, 446, 67, 1, 0, 0, 0, 447, 448, 5, 9, 0, 0, 448, 449, 3, 52, 26, 0, 449, 69, 1, 0, 0, 0, 450, 451, 5, 2, 0, 0, 451, 452, 3, 52, 26, 0, 452, 71, 1, 0, 0, 0, 453, 454, 5, 15, 0, 0, 454, 459, 3, 74, 37, 0, 455, 456, 5, 38, 0, 0, 456, 458, 3, 74, 37, 0, 457, 455, 1, 0, 0, 0, 458, 461, 1, 0, 0, 0, 459, 457, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 73, 1, 0, 0, 0, 461, 459, 1, 0, 0, 0, 462, 463, 3, 50, 25, 0, 463, 464, 5, 84, 0, 0, 464, 465, 3, 50, 25, 0, 465, 75, 1, 0, 0, 0, 466, 467, 5, 1, 0, 0, 467, 468, 3, 18, 9, 0, 468, 470, 3, 94, 47, 0, 469, 471, 3, 82, 41, 0, 470, 469, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 77, 1, 0, 0, 0, 472, 473, 5, 7, 0, 0, 473, 474, 3, 18, 9, 0, 474, 475, 3, 94, 47, 0, 475, 79, 1, 0, 0, 0, 476, 477, 5, 14, 0, 0, 477, 478, 3, 48, 24, 0, 478, 81, 1, 0, 0, 0, 479, 484, 3, 84, 42, 0, 480, 481, 5, 38, 0, 0, 481, 483, 3, 84, 42, 0, 482, 480, 1, 0, 0, 0, 483, 486, 1, 0, 0, 0, 484, 482, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 83, 1, 0, 0, 0, 486, 484, 1, 0, 0, 0, 487, 488, 3, 54, 27, 0, 488, 489, 5, 36, 0, 0, 489, 490, 3, 58, 29, 0, 490, 85, 1, 0, 0, 0, 491, 492, 7, 5, 0, 0, 492, 87, 1, 0, 0, 0, 493, 496, 3, 90, 45, 0, 494, 496, 3, 92, 46, 0, 495, 493, 1, 0, 0, 0, 495, 494, 1, 0, 0, 0, 496, 89, 1, 0, 0, 0, 497, 499, 7, 0, 0, 0, 498, 497, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 501, 5, 32, 0, 0, 501, 91, 1, 0, 0, 0, 502, 504, 7, 0, 0, 0, 503, 502, 1, 0, 0, 0, 503, 504, 1, 0, 0, 0, 504, 505, 1, 0, 0, 0, 505, 506, 5, 31, 0, 0, 506, 93, 1, 0, 0, 0, 507, 508, 5, 30, 0, 0, 508, 95, 1, 0, 0, 0, 509, 510, 7, 6, 0, 0, 510, 97, 1, 0, 0, 0, 511, 512, 5, 5, 0, 0, 512, 513, 3, 100, 50, 0, 513, 99, 1, 0, 0, 0, 514, 515, 5, 69, 0, 0, 515, 516, 3, 2, 1, 0, 516, 517, 5, 70, 0, 0, 517, 101, 1, 0, 0, 0, 518, 519, 5, 17, 0, 0, 519, 520, 5, 106, 0, 0, 520, 103, 1, 0, 0, 0, 521, 522, 5, 12, 0, 0, 522, 523, 5, 110, 0, 0, 523, 105, 1, 0, 0, 0, 524, 525, 5, 3, 0, 0, 525, 528, 5, 90, 0, 0, 526, 527, 5, 88, 0, 0, 527, 529, 3, 50, 25, 0, 528, 526, 1, 0, 0, 0, 528, 529, 1, 0, 0, 0, 529, 539, 1, 0, 0, 0, 530, 531, 5, 89, 0, 0, 531, 536, 3, 108, 54, 0, 532, 533, 5, 38, 0, 0, 533, 535, 3, 108, 54, 0, 534, 532, 1, 0, 0, 0, 535, 538, 1, 0, 0, 0, 536, 534, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 540, 1, 0, 0, 0, 538, 536, 1, 0, 0, 0, 539, 530, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 107, 1, 0, 0, 0, 541, 542, 3, 50, 25, 0, 542, 543, 5, 36, 0, 0, 543, 545, 1, 0, 0, 0, 544, 541, 1, 0, 0, 0, 544, 545, 1, 0, 0, 0, 545, 546, 1, 0, 0, 0, 546, 547, 3, 50, 25, 0, 547, 109, 1, 0, 0, 0, 548, 549, 5, 11, 0, 0, 549, 550, 5, 25, 0, 0, 550, 551, 5, 88, 0, 0, 551, 552, 3, 52, 26, 0, 552, 111, 1, 0, 0, 0, 53, 123, 132, 148, 160, 169, 177, 181, 189, 191, 196, 203, 208, 215, 221, 229, 231, 242, 249, 260, 263, 277, 285, 293, 297, 303, 311, 324, 328, 332, 339, 343, 349, 356, 364, 372, 394, 405, 416, 421, 425, 436, 441, 445, 459, 470, 484, 495, 498, 503, 528, 536, 539, 544] \ 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 1c136a946a0f3..6c21529d6a648 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 @@ -26,22 +26,23 @@ public class EsqlBaseParser extends Parser { CAST_OP=37, COMMA=38, DESC=39, DOT=40, FALSE=41, FIRST=42, LAST=43, LP=44, IN=45, IS=46, LIKE=47, NOT=48, NULL=49, NULLS=50, OR=51, PARAM=52, RLIKE=53, RP=54, TRUE=55, EQ=56, CIEQ=57, NEQ=58, LT=59, LTE=60, GT=61, GTE=62, - PLUS=63, MINUS=64, ASTERISK=65, SLASH=66, PERCENT=67, OPENING_BRACKET=68, - CLOSING_BRACKET=69, UNQUOTED_IDENTIFIER=70, QUOTED_IDENTIFIER=71, EXPR_LINE_COMMENT=72, - EXPR_MULTILINE_COMMENT=73, EXPR_WS=74, METADATA=75, FROM_LINE_COMMENT=76, - FROM_MULTILINE_COMMENT=77, FROM_WS=78, ID_PATTERN=79, PROJECT_LINE_COMMENT=80, - PROJECT_MULTILINE_COMMENT=81, PROJECT_WS=82, AS=83, RENAME_LINE_COMMENT=84, - RENAME_MULTILINE_COMMENT=85, RENAME_WS=86, ON=87, WITH=88, ENRICH_POLICY_NAME=89, - ENRICH_LINE_COMMENT=90, ENRICH_MULTILINE_COMMENT=91, ENRICH_WS=92, ENRICH_FIELD_LINE_COMMENT=93, - ENRICH_FIELD_MULTILINE_COMMENT=94, ENRICH_FIELD_WS=95, LOOKUP_LINE_COMMENT=96, - LOOKUP_MULTILINE_COMMENT=97, LOOKUP_WS=98, LOOKUP_FIELD_LINE_COMMENT=99, - LOOKUP_FIELD_MULTILINE_COMMENT=100, LOOKUP_FIELD_WS=101, MVEXPAND_LINE_COMMENT=102, - MVEXPAND_MULTILINE_COMMENT=103, MVEXPAND_WS=104, INFO=105, SHOW_LINE_COMMENT=106, - SHOW_MULTILINE_COMMENT=107, SHOW_WS=108, FUNCTIONS=109, META_LINE_COMMENT=110, - META_MULTILINE_COMMENT=111, META_WS=112, COLON=113, SETTING=114, SETTING_LINE_COMMENT=115, - SETTTING_MULTILINE_COMMENT=116, SETTING_WS=117, METRICS_LINE_COMMENT=118, - METRICS_MULTILINE_COMMENT=119, METRICS_WS=120, CLOSING_METRICS_LINE_COMMENT=121, - CLOSING_METRICS_MULTILINE_COMMENT=122, CLOSING_METRICS_WS=123; + PLUS=63, MINUS=64, ASTERISK=65, SLASH=66, PERCENT=67, NAMED_OR_POSITIONAL_PARAM=68, + OPENING_BRACKET=69, CLOSING_BRACKET=70, UNQUOTED_IDENTIFIER=71, QUOTED_IDENTIFIER=72, + EXPR_LINE_COMMENT=73, EXPR_MULTILINE_COMMENT=74, EXPR_WS=75, METADATA=76, + FROM_LINE_COMMENT=77, FROM_MULTILINE_COMMENT=78, FROM_WS=79, ID_PATTERN=80, + PROJECT_LINE_COMMENT=81, PROJECT_MULTILINE_COMMENT=82, PROJECT_WS=83, + AS=84, RENAME_LINE_COMMENT=85, RENAME_MULTILINE_COMMENT=86, RENAME_WS=87, + ON=88, WITH=89, ENRICH_POLICY_NAME=90, ENRICH_LINE_COMMENT=91, ENRICH_MULTILINE_COMMENT=92, + ENRICH_WS=93, ENRICH_FIELD_LINE_COMMENT=94, ENRICH_FIELD_MULTILINE_COMMENT=95, + ENRICH_FIELD_WS=96, LOOKUP_LINE_COMMENT=97, LOOKUP_MULTILINE_COMMENT=98, + LOOKUP_WS=99, LOOKUP_FIELD_LINE_COMMENT=100, LOOKUP_FIELD_MULTILINE_COMMENT=101, + LOOKUP_FIELD_WS=102, MVEXPAND_LINE_COMMENT=103, MVEXPAND_MULTILINE_COMMENT=104, + MVEXPAND_WS=105, INFO=106, SHOW_LINE_COMMENT=107, SHOW_MULTILINE_COMMENT=108, + SHOW_WS=109, FUNCTIONS=110, META_LINE_COMMENT=111, META_MULTILINE_COMMENT=112, + META_WS=113, COLON=114, SETTING=115, SETTING_LINE_COMMENT=116, SETTTING_MULTILINE_COMMENT=117, + SETTING_WS=118, METRICS_LINE_COMMENT=119, METRICS_MULTILINE_COMMENT=120, + METRICS_WS=121, CLOSING_METRICS_LINE_COMMENT=122, CLOSING_METRICS_MULTILINE_COMMENT=123, + CLOSING_METRICS_WS=124; 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, @@ -52,15 +53,15 @@ public class EsqlBaseParser extends Parser { RULE_metricsCommand = 20, RULE_evalCommand = 21, RULE_statsCommand = 22, RULE_inlinestatsCommand = 23, RULE_qualifiedName = 24, RULE_qualifiedNamePattern = 25, RULE_qualifiedNamePatterns = 26, RULE_identifier = 27, RULE_identifierPattern = 28, - RULE_constant = 29, RULE_limitCommand = 30, RULE_sortCommand = 31, RULE_orderExpression = 32, - RULE_keepCommand = 33, RULE_dropCommand = 34, RULE_renameCommand = 35, - RULE_renameClause = 36, RULE_dissectCommand = 37, RULE_grokCommand = 38, - RULE_mvExpandCommand = 39, RULE_commandOptions = 40, RULE_commandOption = 41, - RULE_booleanValue = 42, RULE_numericValue = 43, RULE_decimalValue = 44, - RULE_integerValue = 45, RULE_string = 46, RULE_comparisonOperator = 47, - RULE_explainCommand = 48, RULE_subqueryExpression = 49, RULE_showCommand = 50, - RULE_metaCommand = 51, RULE_enrichCommand = 52, RULE_enrichWithClause = 53, - RULE_lookupCommand = 54; + RULE_constant = 29, RULE_params = 30, RULE_limitCommand = 31, RULE_sortCommand = 32, + RULE_orderExpression = 33, RULE_keepCommand = 34, RULE_dropCommand = 35, + RULE_renameCommand = 36, RULE_renameClause = 37, RULE_dissectCommand = 38, + RULE_grokCommand = 39, RULE_mvExpandCommand = 40, RULE_commandOptions = 41, + RULE_commandOption = 42, RULE_booleanValue = 43, RULE_numericValue = 44, + RULE_decimalValue = 45, RULE_integerValue = 46, RULE_string = 47, RULE_comparisonOperator = 48, + RULE_explainCommand = 49, RULE_subqueryExpression = 50, RULE_showCommand = 51, + RULE_metaCommand = 52, RULE_enrichCommand = 53, RULE_enrichWithClause = 54, + RULE_lookupCommand = 55; private static String[] makeRuleNames() { return new String[] { "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", @@ -69,9 +70,9 @@ private static String[] makeRuleNames() { "fields", "field", "fromCommand", "indexIdentifier", "metadata", "metadataOption", "deprecated_metadata", "metricsCommand", "evalCommand", "statsCommand", "inlinestatsCommand", "qualifiedName", "qualifiedNamePattern", "qualifiedNamePatterns", - "identifier", "identifierPattern", "constant", "limitCommand", "sortCommand", - "orderExpression", "keepCommand", "dropCommand", "renameCommand", "renameClause", - "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", + "identifier", "identifierPattern", "constant", "params", "limitCommand", + "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", "commandOption", "booleanValue", "numericValue", "decimalValue", "integerValue", "string", "comparisonOperator", "explainCommand", "subqueryExpression", "showCommand", "metaCommand", "enrichCommand", "enrichWithClause", "lookupCommand" @@ -89,11 +90,11 @@ private static String[] makeLiteralNames() { "'desc'", "'.'", "'false'", "'first'", "'last'", "'('", "'in'", "'is'", "'like'", "'not'", "'null'", "'nulls'", "'or'", "'?'", "'rlike'", "')'", "'true'", "'=='", "'=~'", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", - "'-'", "'*'", "'/'", "'%'", null, "']'", null, null, null, null, null, - "'metadata'", null, null, null, null, null, null, null, "'as'", null, - null, null, "'on'", "'with'", null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, "'info'", null, - null, null, "'functions'", null, null, null, "':'" + "'-'", "'*'", "'/'", "'%'", null, null, "']'", null, null, null, null, + null, "'metadata'", null, null, null, null, null, null, null, "'as'", + null, null, null, "'on'", "'with'", null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "'info'", + null, null, null, "'functions'", null, null, null, "':'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); @@ -108,21 +109,21 @@ private static String[] makeSymbolicNames() { "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "EQ", "CIEQ", "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", - "METADATA", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", - "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", - "AS", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", - "ON", "WITH", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", - "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", - "ENRICH_FIELD_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", - "LOOKUP_WS", "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", - "LOOKUP_FIELD_WS", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", - "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", - "SHOW_WS", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", - "META_WS", "COLON", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", - "SETTING_WS", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", - "CLOSING_METRICS_LINE_COMMENT", "CLOSING_METRICS_MULTILINE_COMMENT", + "PERCENT", "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "METADATA", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", + "FROM_WS", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", + "PROJECT_WS", "AS", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", + "RENAME_WS", "ON", "WITH", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", + "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", + "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "LOOKUP_LINE_COMMENT", + "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", "LOOKUP_FIELD_LINE_COMMENT", + "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", "MVEXPAND_LINE_COMMENT", + "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", "INFO", "SHOW_LINE_COMMENT", + "SHOW_MULTILINE_COMMENT", "SHOW_WS", "FUNCTIONS", "META_LINE_COMMENT", + "META_MULTILINE_COMMENT", "META_WS", "COLON", "SETTING", "SETTING_LINE_COMMENT", + "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", + "METRICS_WS", "CLOSING_METRICS_LINE_COMMENT", "CLOSING_METRICS_MULTILINE_COMMENT", "CLOSING_METRICS_WS" }; } @@ -210,9 +211,9 @@ public final SingleStatementContext singleStatement() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(110); + setState(112); query(0); - setState(111); + setState(113); match(EOF); } } @@ -308,11 +309,11 @@ private QueryContext query(int _p) throws RecognitionException { _ctx = _localctx; _prevctx = _localctx; - setState(114); + setState(116); sourceCommand(); } _ctx.stop = _input.LT(-1); - setState(121); + setState(123); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,0,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -323,16 +324,16 @@ private QueryContext query(int _p) throws RecognitionException { { _localctx = new CompositeQueryContext(new QueryContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_query); - setState(116); + setState(118); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(117); + setState(119); match(PIPE); - setState(118); + setState(120); processingCommand(); } } } - setState(123); + setState(125); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,0,_ctx); } @@ -393,48 +394,48 @@ public final SourceCommandContext sourceCommand() throws RecognitionException { SourceCommandContext _localctx = new SourceCommandContext(_ctx, getState()); enterRule(_localctx, 4, RULE_sourceCommand); try { - setState(130); + setState(132); _errHandler.sync(this); switch (_input.LA(1)) { case EXPLAIN: enterOuterAlt(_localctx, 1); { - setState(124); + setState(126); explainCommand(); } break; case FROM: enterOuterAlt(_localctx, 2); { - setState(125); + setState(127); fromCommand(); } break; case ROW: enterOuterAlt(_localctx, 3); { - setState(126); + setState(128); rowCommand(); } break; case METRICS: enterOuterAlt(_localctx, 4); { - setState(127); + setState(129); metricsCommand(); } break; case SHOW: enterOuterAlt(_localctx, 5); { - setState(128); + setState(130); showCommand(); } break; case META: enterOuterAlt(_localctx, 6); { - setState(129); + setState(131); metaCommand(); } break; @@ -521,104 +522,104 @@ public final ProcessingCommandContext processingCommand() throws RecognitionExce ProcessingCommandContext _localctx = new ProcessingCommandContext(_ctx, getState()); enterRule(_localctx, 6, RULE_processingCommand); try { - setState(146); + setState(148); _errHandler.sync(this); switch (_input.LA(1)) { case EVAL: enterOuterAlt(_localctx, 1); { - setState(132); + setState(134); evalCommand(); } break; case INLINESTATS: enterOuterAlt(_localctx, 2); { - setState(133); + setState(135); inlinestatsCommand(); } break; case LIMIT: enterOuterAlt(_localctx, 3); { - setState(134); + setState(136); limitCommand(); } break; case LOOKUP: enterOuterAlt(_localctx, 4); { - setState(135); + setState(137); lookupCommand(); } break; case KEEP: enterOuterAlt(_localctx, 5); { - setState(136); + setState(138); keepCommand(); } break; case SORT: enterOuterAlt(_localctx, 6); { - setState(137); + setState(139); sortCommand(); } break; case STATS: enterOuterAlt(_localctx, 7); { - setState(138); + setState(140); statsCommand(); } break; case WHERE: enterOuterAlt(_localctx, 8); { - setState(139); + setState(141); whereCommand(); } break; case DROP: enterOuterAlt(_localctx, 9); { - setState(140); + setState(142); dropCommand(); } break; case RENAME: enterOuterAlt(_localctx, 10); { - setState(141); + setState(143); renameCommand(); } break; case DISSECT: enterOuterAlt(_localctx, 11); { - setState(142); + setState(144); dissectCommand(); } break; case GROK: enterOuterAlt(_localctx, 12); { - setState(143); + setState(145); grokCommand(); } break; case ENRICH: enterOuterAlt(_localctx, 13); { - setState(144); + setState(146); enrichCommand(); } break; case MV_EXPAND: enterOuterAlt(_localctx, 14); { - setState(145); + setState(147); mvExpandCommand(); } break; @@ -669,9 +670,9 @@ public final WhereCommandContext whereCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(148); + setState(150); match(WHERE); - setState(149); + setState(151); booleanExpression(0); } } @@ -866,7 +867,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(179); + setState(181); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: @@ -875,9 +876,9 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _ctx = _localctx; _prevctx = _localctx; - setState(152); + setState(154); match(NOT); - setState(153); + setState(155); booleanExpression(7); } break; @@ -886,7 +887,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(154); + setState(156); valueExpression(); } break; @@ -895,7 +896,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new RegexExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(155); + setState(157); regexBooleanExpression(); } break; @@ -904,41 +905,41 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalInContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(156); - valueExpression(); setState(158); + valueExpression(); + setState(160); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(157); + setState(159); match(NOT); } } - setState(160); + setState(162); match(IN); - setState(161); + setState(163); match(LP); - setState(162); + setState(164); valueExpression(); - setState(167); + setState(169); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(163); + setState(165); match(COMMA); - setState(164); + setState(166); valueExpression(); } } - setState(169); + setState(171); _errHandler.sync(this); _la = _input.LA(1); } - setState(170); + setState(172); match(RP); } break; @@ -947,27 +948,27 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new IsNullContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(172); + setState(174); valueExpression(); - setState(173); - match(IS); setState(175); + match(IS); + setState(177); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(174); + setState(176); match(NOT); } } - setState(177); + setState(179); match(NULL); } break; } _ctx.stop = _input.LT(-1); - setState(189); + setState(191); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,8,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -975,7 +976,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(187); + setState(189); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { case 1: @@ -983,11 +984,11 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(181); + setState(183); if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); - setState(182); + setState(184); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(183); + setState(185); ((LogicalBinaryContext)_localctx).right = booleanExpression(5); } break; @@ -996,18 +997,18 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(184); + setState(186); if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(185); + setState(187); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(186); + setState(188); ((LogicalBinaryContext)_localctx).right = booleanExpression(4); } break; } } } - setState(191); + setState(193); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,8,_ctx); } @@ -1062,48 +1063,48 @@ public final RegexBooleanExpressionContext regexBooleanExpression() throws Recog enterRule(_localctx, 12, RULE_regexBooleanExpression); int _la; try { - setState(206); + setState(208); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(192); - valueExpression(); setState(194); + valueExpression(); + setState(196); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(193); + setState(195); match(NOT); } } - setState(196); + setState(198); ((RegexBooleanExpressionContext)_localctx).kind = match(LIKE); - setState(197); + setState(199); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(199); - valueExpression(); setState(201); + valueExpression(); + setState(203); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(200); + setState(202); match(NOT); } } - setState(203); + setState(205); ((RegexBooleanExpressionContext)_localctx).kind = match(RLIKE); - setState(204); + setState(206); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; @@ -1189,14 +1190,14 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, getState()); enterRule(_localctx, 14, RULE_valueExpression); try { - setState(213); + setState(215); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { case 1: _localctx = new ValueExpressionDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(208); + setState(210); operatorExpression(0); } break; @@ -1204,11 +1205,11 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio _localctx = new ComparisonContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(209); + setState(211); ((ComparisonContext)_localctx).left = operatorExpression(0); - setState(210); + setState(212); comparisonOperator(); - setState(211); + setState(213); ((ComparisonContext)_localctx).right = operatorExpression(0); } break; @@ -1333,7 +1334,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE int _alt; enterOuterAlt(_localctx, 1); { - setState(219); + setState(221); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: @@ -1342,7 +1343,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _ctx = _localctx; _prevctx = _localctx; - setState(216); + setState(218); primaryExpression(0); } break; @@ -1351,7 +1352,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(217); + setState(219); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1362,13 +1363,13 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(218); + setState(220); operatorExpression(3); } break; } _ctx.stop = _input.LT(-1); - setState(229); + setState(231); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,15,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -1376,7 +1377,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(227); + setState(229); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { case 1: @@ -1384,9 +1385,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(221); + setState(223); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(222); + setState(224); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & 7L) != 0)) ) { @@ -1397,7 +1398,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(223); + setState(225); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3); } break; @@ -1406,9 +1407,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(224); + setState(226); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(225); + setState(227); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -1419,14 +1420,14 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(226); + setState(228); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(2); } break; } } } - setState(231); + setState(233); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,15,_ctx); } @@ -1584,7 +1585,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(240); + setState(242); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) { case 1: @@ -1593,7 +1594,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _ctx = _localctx; _prevctx = _localctx; - setState(233); + setState(235); constant(); } break; @@ -1602,7 +1603,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new DereferenceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(234); + setState(236); qualifiedName(); } break; @@ -1611,7 +1612,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new FunctionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(235); + setState(237); functionExpression(); } break; @@ -1620,17 +1621,17 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new ParenthesizedExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(236); + setState(238); match(LP); - setState(237); + setState(239); booleanExpression(0); - setState(238); + setState(240); match(RP); } break; } _ctx.stop = _input.LT(-1); - setState(247); + setState(249); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -1641,16 +1642,16 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc { _localctx = new InlineCastContext(new PrimaryExpressionContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_primaryExpression); - setState(242); + setState(244); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(243); + setState(245); match(CAST_OP); - setState(244); + setState(246); dataType(); } } } - setState(249); + setState(251); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); } @@ -1712,16 +1713,16 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(250); + setState(252); identifier(); - setState(251); + setState(253); match(LP); - setState(261); + setState(263); _errHandler.sync(this); switch (_input.LA(1)) { case ASTERISK: { - setState(252); + setState(254); match(ASTERISK); } break; @@ -1736,26 +1737,27 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx case TRUE: case PLUS: case MINUS: + case NAMED_OR_POSITIONAL_PARAM: case OPENING_BRACKET: case UNQUOTED_IDENTIFIER: case QUOTED_IDENTIFIER: { { - setState(253); + setState(255); booleanExpression(0); - setState(258); + setState(260); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(254); + setState(256); match(COMMA); - setState(255); + setState(257); booleanExpression(0); } } - setState(260); + setState(262); _errHandler.sync(this); _la = _input.LA(1); } @@ -1767,7 +1769,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx default: break; } - setState(263); + setState(265); match(RP); } } @@ -1825,7 +1827,7 @@ public final DataTypeContext dataType() throws RecognitionException { _localctx = new ToDataTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(265); + setState(267); identifier(); } } @@ -1872,9 +1874,9 @@ public final RowCommandContext rowCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(267); + setState(269); match(ROW); - setState(268); + setState(270); fields(); } } @@ -1928,23 +1930,23 @@ public final FieldsContext fields() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(270); + setState(272); field(); - setState(275); + setState(277); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(271); + setState(273); match(COMMA); - setState(272); + setState(274); field(); } } } - setState(277); + setState(279); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); } @@ -1994,24 +1996,24 @@ public final FieldContext field() throws RecognitionException { FieldContext _localctx = new FieldContext(_ctx, getState()); enterRule(_localctx, 28, RULE_field); try { - setState(283); + setState(285); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(278); + setState(280); booleanExpression(0); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(279); + setState(281); qualifiedName(); - setState(280); + setState(282); match(ASSIGN); - setState(281); + setState(283); booleanExpression(0); } break; @@ -2071,34 +2073,34 @@ public final FromCommandContext fromCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(285); + setState(287); match(FROM); - setState(286); + setState(288); indexIdentifier(); - setState(291); + setState(293); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,22,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(287); + setState(289); match(COMMA); - setState(288); + setState(290); indexIdentifier(); } } } - setState(293); + setState(295); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,22,_ctx); } - setState(295); + setState(297); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) { case 1: { - setState(294); + setState(296); metadata(); } break; @@ -2145,7 +2147,7 @@ public final IndexIdentifierContext indexIdentifier() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(297); + setState(299); match(INDEX_UNQUOTED_IDENTIFIER); } } @@ -2192,20 +2194,20 @@ public final MetadataContext metadata() throws RecognitionException { MetadataContext _localctx = new MetadataContext(_ctx, getState()); enterRule(_localctx, 34, RULE_metadata); try { - setState(301); + setState(303); _errHandler.sync(this); switch (_input.LA(1)) { case METADATA: enterOuterAlt(_localctx, 1); { - setState(299); + setState(301); metadataOption(); } break; case OPENING_BRACKET: enterOuterAlt(_localctx, 2); { - setState(300); + setState(302); deprecated_metadata(); } break; @@ -2264,25 +2266,25 @@ public final MetadataOptionContext metadataOption() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(303); + setState(305); match(METADATA); - setState(304); + setState(306); indexIdentifier(); - setState(309); + setState(311); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,25,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(305); + setState(307); match(COMMA); - setState(306); + setState(308); indexIdentifier(); } } } - setState(311); + setState(313); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,25,_ctx); } @@ -2331,11 +2333,11 @@ public final Deprecated_metadataContext deprecated_metadata() throws Recognition try { enterOuterAlt(_localctx, 1); { - setState(312); + setState(314); match(OPENING_BRACKET); - setState(313); + setState(315); metadataOption(); - setState(314); + setState(316); match(CLOSING_BRACKET); } } @@ -2399,46 +2401,46 @@ public final MetricsCommandContext metricsCommand() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(316); + setState(318); match(METRICS); - setState(317); + setState(319); indexIdentifier(); - setState(322); + setState(324); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,26,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(318); + setState(320); match(COMMA); - setState(319); + setState(321); indexIdentifier(); } } } - setState(324); + setState(326); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,26,_ctx); } - setState(326); + setState(328); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { case 1: { - setState(325); + setState(327); ((MetricsCommandContext)_localctx).aggregates = fields(); } break; } - setState(330); + setState(332); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) { case 1: { - setState(328); + setState(330); match(BY); - setState(329); + setState(331); ((MetricsCommandContext)_localctx).grouping = fields(); } break; @@ -2488,9 +2490,9 @@ public final EvalCommandContext evalCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(332); + setState(334); match(EVAL); - setState(333); + setState(335); fields(); } } @@ -2543,26 +2545,26 @@ public final StatsCommandContext statsCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(335); - match(STATS); setState(337); + match(STATS); + setState(339); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) { case 1: { - setState(336); + setState(338); ((StatsCommandContext)_localctx).stats = fields(); } break; } - setState(341); + setState(343); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) { case 1: { - setState(339); + setState(341); match(BY); - setState(340); + setState(342); ((StatsCommandContext)_localctx).grouping = fields(); } break; @@ -2618,18 +2620,18 @@ public final InlinestatsCommandContext inlinestatsCommand() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(343); + setState(345); match(INLINESTATS); - setState(344); + setState(346); ((InlinestatsCommandContext)_localctx).stats = fields(); - setState(347); + setState(349); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { case 1: { - setState(345); + setState(347); match(BY); - setState(346); + setState(348); ((InlinestatsCommandContext)_localctx).grouping = fields(); } break; @@ -2686,23 +2688,23 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(349); + setState(351); identifier(); - setState(354); + setState(356); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,32,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(350); + setState(352); match(DOT); - setState(351); + setState(353); identifier(); } } } - setState(356); + setState(358); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,32,_ctx); } @@ -2758,23 +2760,23 @@ public final QualifiedNamePatternContext qualifiedNamePattern() throws Recogniti int _alt; enterOuterAlt(_localctx, 1); { - setState(357); + setState(359); identifierPattern(); - setState(362); + setState(364); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,33,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(358); + setState(360); match(DOT); - setState(359); + setState(361); identifierPattern(); } } } - setState(364); + setState(366); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,33,_ctx); } @@ -2830,23 +2832,23 @@ public final QualifiedNamePatternsContext qualifiedNamePatterns() throws Recogni int _alt; enterOuterAlt(_localctx, 1); { - setState(365); + setState(367); qualifiedNamePattern(); - setState(370); + setState(372); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,34,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(366); + setState(368); match(COMMA); - setState(367); + setState(369); qualifiedNamePattern(); } } } - setState(372); + setState(374); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,34,_ctx); } @@ -2894,7 +2896,7 @@ public final IdentifierContext identifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(373); + setState(375); _la = _input.LA(1); if ( !(_la==UNQUOTED_IDENTIFIER || _la==QUOTED_IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2946,7 +2948,7 @@ public final IdentifierPatternContext identifierPattern() throws RecognitionExce try { enterOuterAlt(_localctx, 1); { - setState(375); + setState(377); match(ID_PATTERN); } } @@ -3149,21 +3151,23 @@ public T accept(ParseTreeVisitor visitor) { } } @SuppressWarnings("CheckReturnValue") - public static class InputParamContext extends ConstantContext { - public TerminalNode PARAM() { return getToken(EsqlBaseParser.PARAM, 0); } + public static class InputParamsContext extends ConstantContext { + public ParamsContext params() { + return getRuleContext(ParamsContext.class,0); + } @SuppressWarnings("this-escape") - public InputParamContext(ConstantContext ctx) { copyFrom(ctx); } + public InputParamsContext(ConstantContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterInputParam(this); + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterInputParams(this); } @Override public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitInputParam(this); + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitInputParams(this); } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor)visitor).visitInputParam(this); + if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor)visitor).visitInputParams(this); else return visitor.visitChildren(this); } } @@ -3215,14 +3219,14 @@ public final ConstantContext constant() throws RecognitionException { enterRule(_localctx, 58, RULE_constant); int _la; try { - setState(419); + setState(421); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) { case 1: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(377); + setState(379); match(NULL); } break; @@ -3230,9 +3234,9 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new QualifiedIntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(378); + setState(380); integerValue(); - setState(379); + setState(381); match(UNQUOTED_IDENTIFIER); } break; @@ -3240,7 +3244,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(381); + setState(383); decimalValue(); } break; @@ -3248,7 +3252,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(382); + setState(384); integerValue(); } break; @@ -3256,23 +3260,23 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(383); + setState(385); booleanValue(); } break; case 6: - _localctx = new InputParamContext(_localctx); + _localctx = new InputParamsContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(384); - match(PARAM); + setState(386); + params(); } break; case 7: _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(385); + setState(387); string(); } break; @@ -3280,27 +3284,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(386); + setState(388); match(OPENING_BRACKET); - setState(387); + setState(389); numericValue(); - setState(392); + setState(394); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(388); + setState(390); match(COMMA); - setState(389); + setState(391); numericValue(); } } - setState(394); + setState(396); _errHandler.sync(this); _la = _input.LA(1); } - setState(395); + setState(397); match(CLOSING_BRACKET); } break; @@ -3308,27 +3312,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(397); + setState(399); match(OPENING_BRACKET); - setState(398); + setState(400); booleanValue(); - setState(403); + setState(405); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(399); + setState(401); match(COMMA); - setState(400); + setState(402); booleanValue(); } } - setState(405); + setState(407); _errHandler.sync(this); _la = _input.LA(1); } - setState(406); + setState(408); match(CLOSING_BRACKET); } break; @@ -3336,27 +3340,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(408); + setState(410); match(OPENING_BRACKET); - setState(409); + setState(411); string(); - setState(414); + setState(416); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(410); + setState(412); match(COMMA); - setState(411); + setState(413); string(); } } - setState(416); + setState(418); _errHandler.sync(this); _la = _input.LA(1); } - setState(417); + setState(419); match(CLOSING_BRACKET); } break; @@ -3373,6 +3377,97 @@ public final ConstantContext constant() throws RecognitionException { return _localctx; } + @SuppressWarnings("CheckReturnValue") + public static class ParamsContext extends ParserRuleContext { + @SuppressWarnings("this-escape") + public ParamsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_params; } + + @SuppressWarnings("this-escape") + public ParamsContext() { } + public void copyFrom(ParamsContext ctx) { + super.copyFrom(ctx); + } + } + @SuppressWarnings("CheckReturnValue") + public static class InputNamedOrPositionalParamContext extends ParamsContext { + public TerminalNode NAMED_OR_POSITIONAL_PARAM() { return getToken(EsqlBaseParser.NAMED_OR_POSITIONAL_PARAM, 0); } + @SuppressWarnings("this-escape") + public InputNamedOrPositionalParamContext(ParamsContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterInputNamedOrPositionalParam(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitInputNamedOrPositionalParam(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor)visitor).visitInputNamedOrPositionalParam(this); + else return visitor.visitChildren(this); + } + } + @SuppressWarnings("CheckReturnValue") + public static class InputParamContext extends ParamsContext { + public TerminalNode PARAM() { return getToken(EsqlBaseParser.PARAM, 0); } + @SuppressWarnings("this-escape") + public InputParamContext(ParamsContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).enterInputParam(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof EsqlBaseParserListener ) ((EsqlBaseParserListener)listener).exitInputParam(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof EsqlBaseParserVisitor ) return ((EsqlBaseParserVisitor)visitor).visitInputParam(this); + else return visitor.visitChildren(this); + } + } + + public final ParamsContext params() throws RecognitionException { + ParamsContext _localctx = new ParamsContext(_ctx, getState()); + enterRule(_localctx, 60, RULE_params); + try { + setState(425); + _errHandler.sync(this); + switch (_input.LA(1)) { + case PARAM: + _localctx = new InputParamContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(423); + match(PARAM); + } + break; + case NAMED_OR_POSITIONAL_PARAM: + _localctx = new InputNamedOrPositionalParamContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(424); + match(NAMED_OR_POSITIONAL_PARAM); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + @SuppressWarnings("CheckReturnValue") public static class LimitCommandContext extends ParserRuleContext { public TerminalNode LIMIT() { return getToken(EsqlBaseParser.LIMIT, 0); } @@ -3399,13 +3494,13 @@ public T accept(ParseTreeVisitor visitor) { public final LimitCommandContext limitCommand() throws RecognitionException { LimitCommandContext _localctx = new LimitCommandContext(_ctx, getState()); - enterRule(_localctx, 60, RULE_limitCommand); + enterRule(_localctx, 62, RULE_limitCommand); try { enterOuterAlt(_localctx, 1); { - setState(421); + setState(427); match(LIMIT); - setState(422); + setState(428); match(INTEGER_LITERAL); } } @@ -3455,32 +3550,32 @@ public T accept(ParseTreeVisitor visitor) { public final SortCommandContext sortCommand() throws RecognitionException { SortCommandContext _localctx = new SortCommandContext(_ctx, getState()); - enterRule(_localctx, 62, RULE_sortCommand); + enterRule(_localctx, 64, RULE_sortCommand); try { int _alt; enterOuterAlt(_localctx, 1); { - setState(424); + setState(430); match(SORT); - setState(425); + setState(431); orderExpression(); - setState(430); + setState(436); _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(426); + setState(432); match(COMMA); - setState(427); + setState(433); orderExpression(); } } } - setState(432); + setState(438); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,39,_ctx); + _alt = getInterpreter().adaptivePredict(_input,40,_ctx); } } } @@ -3529,19 +3624,19 @@ public T accept(ParseTreeVisitor visitor) { public final OrderExpressionContext orderExpression() throws RecognitionException { OrderExpressionContext _localctx = new OrderExpressionContext(_ctx, getState()); - enterRule(_localctx, 64, RULE_orderExpression); + enterRule(_localctx, 66, RULE_orderExpression); int _la; try { enterOuterAlt(_localctx, 1); { - setState(433); + setState(439); booleanExpression(0); - setState(435); + setState(441); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,41,_ctx) ) { case 1: { - setState(434); + setState(440); ((OrderExpressionContext)_localctx).ordering = _input.LT(1); _la = _input.LA(1); if ( !(_la==ASC || _la==DESC) ) { @@ -3555,14 +3650,14 @@ public final OrderExpressionContext orderExpression() throws RecognitionExceptio } break; } - setState(439); + setState(445); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,41,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { case 1: { - setState(437); + setState(443); match(NULLS); - setState(438); + setState(444); ((OrderExpressionContext)_localctx).nullOrdering = _input.LT(1); _la = _input.LA(1); if ( !(_la==FIRST || _la==LAST) ) { @@ -3617,13 +3712,13 @@ public T accept(ParseTreeVisitor visitor) { public final KeepCommandContext keepCommand() throws RecognitionException { KeepCommandContext _localctx = new KeepCommandContext(_ctx, getState()); - enterRule(_localctx, 66, RULE_keepCommand); + enterRule(_localctx, 68, RULE_keepCommand); try { enterOuterAlt(_localctx, 1); { - setState(441); + setState(447); match(KEEP); - setState(442); + setState(448); qualifiedNamePatterns(); } } @@ -3666,13 +3761,13 @@ public T accept(ParseTreeVisitor visitor) { public final DropCommandContext dropCommand() throws RecognitionException { DropCommandContext _localctx = new DropCommandContext(_ctx, getState()); - enterRule(_localctx, 68, RULE_dropCommand); + enterRule(_localctx, 70, RULE_dropCommand); try { enterOuterAlt(_localctx, 1); { - setState(444); + setState(450); match(DROP); - setState(445); + setState(451); qualifiedNamePatterns(); } } @@ -3722,32 +3817,32 @@ public T accept(ParseTreeVisitor visitor) { public final RenameCommandContext renameCommand() throws RecognitionException { RenameCommandContext _localctx = new RenameCommandContext(_ctx, getState()); - enterRule(_localctx, 70, RULE_renameCommand); + enterRule(_localctx, 72, RULE_renameCommand); try { int _alt; enterOuterAlt(_localctx, 1); { - setState(447); + setState(453); match(RENAME); - setState(448); + setState(454); renameClause(); - setState(453); + setState(459); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,42,_ctx); + _alt = getInterpreter().adaptivePredict(_input,43,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(449); + setState(455); match(COMMA); - setState(450); + setState(456); renameClause(); } } } - setState(455); + setState(461); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,42,_ctx); + _alt = getInterpreter().adaptivePredict(_input,43,_ctx); } } } @@ -3795,15 +3890,15 @@ public T accept(ParseTreeVisitor visitor) { public final RenameClauseContext renameClause() throws RecognitionException { RenameClauseContext _localctx = new RenameClauseContext(_ctx, getState()); - enterRule(_localctx, 72, RULE_renameClause); + enterRule(_localctx, 74, RULE_renameClause); try { enterOuterAlt(_localctx, 1); { - setState(456); + setState(462); ((RenameClauseContext)_localctx).oldName = qualifiedNamePattern(); - setState(457); + setState(463); match(AS); - setState(458); + setState(464); ((RenameClauseContext)_localctx).newName = qualifiedNamePattern(); } } @@ -3852,22 +3947,22 @@ public T accept(ParseTreeVisitor visitor) { public final DissectCommandContext dissectCommand() throws RecognitionException { DissectCommandContext _localctx = new DissectCommandContext(_ctx, getState()); - enterRule(_localctx, 74, RULE_dissectCommand); + enterRule(_localctx, 76, RULE_dissectCommand); try { enterOuterAlt(_localctx, 1); { - setState(460); + setState(466); match(DISSECT); - setState(461); + setState(467); primaryExpression(0); - setState(462); + setState(468); string(); - setState(464); + setState(470); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,43,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,44,_ctx) ) { case 1: { - setState(463); + setState(469); commandOptions(); } break; @@ -3916,15 +4011,15 @@ public T accept(ParseTreeVisitor visitor) { public final GrokCommandContext grokCommand() throws RecognitionException { GrokCommandContext _localctx = new GrokCommandContext(_ctx, getState()); - enterRule(_localctx, 76, RULE_grokCommand); + enterRule(_localctx, 78, RULE_grokCommand); try { enterOuterAlt(_localctx, 1); { - setState(466); + setState(472); match(GROK); - setState(467); + setState(473); primaryExpression(0); - setState(468); + setState(474); string(); } } @@ -3967,13 +4062,13 @@ public T accept(ParseTreeVisitor visitor) { public final MvExpandCommandContext mvExpandCommand() throws RecognitionException { MvExpandCommandContext _localctx = new MvExpandCommandContext(_ctx, getState()); - enterRule(_localctx, 78, RULE_mvExpandCommand); + enterRule(_localctx, 80, RULE_mvExpandCommand); try { enterOuterAlt(_localctx, 1); { - setState(470); + setState(476); match(MV_EXPAND); - setState(471); + setState(477); qualifiedName(); } } @@ -4022,30 +4117,30 @@ public T accept(ParseTreeVisitor visitor) { public final CommandOptionsContext commandOptions() throws RecognitionException { CommandOptionsContext _localctx = new CommandOptionsContext(_ctx, getState()); - enterRule(_localctx, 80, RULE_commandOptions); + enterRule(_localctx, 82, RULE_commandOptions); try { int _alt; enterOuterAlt(_localctx, 1); { - setState(473); + setState(479); commandOption(); - setState(478); + setState(484); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + _alt = getInterpreter().adaptivePredict(_input,45,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(474); + setState(480); match(COMMA); - setState(475); + setState(481); commandOption(); } } } - setState(480); + setState(486); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + _alt = getInterpreter().adaptivePredict(_input,45,_ctx); } } } @@ -4091,15 +4186,15 @@ public T accept(ParseTreeVisitor visitor) { public final CommandOptionContext commandOption() throws RecognitionException { CommandOptionContext _localctx = new CommandOptionContext(_ctx, getState()); - enterRule(_localctx, 82, RULE_commandOption); + enterRule(_localctx, 84, RULE_commandOption); try { enterOuterAlt(_localctx, 1); { - setState(481); + setState(487); identifier(); - setState(482); + setState(488); match(ASSIGN); - setState(483); + setState(489); constant(); } } @@ -4140,12 +4235,12 @@ public T accept(ParseTreeVisitor visitor) { public final BooleanValueContext booleanValue() throws RecognitionException { BooleanValueContext _localctx = new BooleanValueContext(_ctx, getState()); - enterRule(_localctx, 84, RULE_booleanValue); + enterRule(_localctx, 86, RULE_booleanValue); int _la; try { enterOuterAlt(_localctx, 1); { - setState(485); + setState(491); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -4198,22 +4293,22 @@ public T accept(ParseTreeVisitor visitor) { public final NumericValueContext numericValue() throws RecognitionException { NumericValueContext _localctx = new NumericValueContext(_ctx, getState()); - enterRule(_localctx, 86, RULE_numericValue); + enterRule(_localctx, 88, RULE_numericValue); try { - setState(489); + setState(495); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,45,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,46,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(487); + setState(493); decimalValue(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(488); + setState(494); integerValue(); } break; @@ -4257,17 +4352,17 @@ public T accept(ParseTreeVisitor visitor) { public final DecimalValueContext decimalValue() throws RecognitionException { DecimalValueContext _localctx = new DecimalValueContext(_ctx, getState()); - enterRule(_localctx, 88, RULE_decimalValue); + enterRule(_localctx, 90, RULE_decimalValue); int _la; try { enterOuterAlt(_localctx, 1); { - setState(492); + setState(498); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(491); + setState(497); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -4280,7 +4375,7 @@ public final DecimalValueContext decimalValue() throws RecognitionException { } } - setState(494); + setState(500); match(DECIMAL_LITERAL); } } @@ -4322,17 +4417,17 @@ public T accept(ParseTreeVisitor visitor) { public final IntegerValueContext integerValue() throws RecognitionException { IntegerValueContext _localctx = new IntegerValueContext(_ctx, getState()); - enterRule(_localctx, 90, RULE_integerValue); + enterRule(_localctx, 92, RULE_integerValue); int _la; try { enterOuterAlt(_localctx, 1); { - setState(497); + setState(503); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(496); + setState(502); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -4345,7 +4440,7 @@ public final IntegerValueContext integerValue() throws RecognitionException { } } - setState(499); + setState(505); match(INTEGER_LITERAL); } } @@ -4385,11 +4480,11 @@ public T accept(ParseTreeVisitor visitor) { public final StringContext string() throws RecognitionException { StringContext _localctx = new StringContext(_ctx, getState()); - enterRule(_localctx, 92, RULE_string); + enterRule(_localctx, 94, RULE_string); try { enterOuterAlt(_localctx, 1); { - setState(501); + setState(507); match(QUOTED_STRING); } } @@ -4434,12 +4529,12 @@ public T accept(ParseTreeVisitor visitor) { public final ComparisonOperatorContext comparisonOperator() throws RecognitionException { ComparisonOperatorContext _localctx = new ComparisonOperatorContext(_ctx, getState()); - enterRule(_localctx, 94, RULE_comparisonOperator); + enterRule(_localctx, 96, RULE_comparisonOperator); int _la; try { enterOuterAlt(_localctx, 1); { - setState(503); + setState(509); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 9007199254740992000L) != 0)) ) { _errHandler.recoverInline(this); @@ -4490,13 +4585,13 @@ public T accept(ParseTreeVisitor visitor) { public final ExplainCommandContext explainCommand() throws RecognitionException { ExplainCommandContext _localctx = new ExplainCommandContext(_ctx, getState()); - enterRule(_localctx, 96, RULE_explainCommand); + enterRule(_localctx, 98, RULE_explainCommand); try { enterOuterAlt(_localctx, 1); { - setState(505); + setState(511); match(EXPLAIN); - setState(506); + setState(512); subqueryExpression(); } } @@ -4540,15 +4635,15 @@ public T accept(ParseTreeVisitor visitor) { public final SubqueryExpressionContext subqueryExpression() throws RecognitionException { SubqueryExpressionContext _localctx = new SubqueryExpressionContext(_ctx, getState()); - enterRule(_localctx, 98, RULE_subqueryExpression); + enterRule(_localctx, 100, RULE_subqueryExpression); try { enterOuterAlt(_localctx, 1); { - setState(508); + setState(514); match(OPENING_BRACKET); - setState(509); + setState(515); query(0); - setState(510); + setState(516); match(CLOSING_BRACKET); } } @@ -4600,14 +4695,14 @@ public T accept(ParseTreeVisitor visitor) { public final ShowCommandContext showCommand() throws RecognitionException { ShowCommandContext _localctx = new ShowCommandContext(_ctx, getState()); - enterRule(_localctx, 100, RULE_showCommand); + enterRule(_localctx, 102, RULE_showCommand); try { _localctx = new ShowInfoContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(512); + setState(518); match(SHOW); - setState(513); + setState(519); match(INFO); } } @@ -4659,14 +4754,14 @@ public T accept(ParseTreeVisitor visitor) { public final MetaCommandContext metaCommand() throws RecognitionException { MetaCommandContext _localctx = new MetaCommandContext(_ctx, getState()); - enterRule(_localctx, 102, RULE_metaCommand); + enterRule(_localctx, 104, RULE_metaCommand); try { _localctx = new MetaFunctionsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(515); + setState(521); match(META); - setState(516); + setState(522); match(FUNCTIONS); } } @@ -4724,53 +4819,53 @@ public T accept(ParseTreeVisitor visitor) { public final EnrichCommandContext enrichCommand() throws RecognitionException { EnrichCommandContext _localctx = new EnrichCommandContext(_ctx, getState()); - enterRule(_localctx, 104, RULE_enrichCommand); + enterRule(_localctx, 106, RULE_enrichCommand); try { int _alt; enterOuterAlt(_localctx, 1); { - setState(518); + setState(524); match(ENRICH); - setState(519); + setState(525); ((EnrichCommandContext)_localctx).policyName = match(ENRICH_POLICY_NAME); - setState(522); + setState(528); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,48,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,49,_ctx) ) { case 1: { - setState(520); + setState(526); match(ON); - setState(521); + setState(527); ((EnrichCommandContext)_localctx).matchField = qualifiedNamePattern(); } break; } - setState(533); + setState(539); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { - setState(524); + setState(530); match(WITH); - setState(525); + setState(531); enrichWithClause(); - setState(530); + setState(536); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,49,_ctx); + _alt = getInterpreter().adaptivePredict(_input,50,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(526); + setState(532); match(COMMA); - setState(527); + setState(533); enrichWithClause(); } } } - setState(532); + setState(538); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,49,_ctx); + _alt = getInterpreter().adaptivePredict(_input,50,_ctx); } } break; @@ -4821,23 +4916,23 @@ public T accept(ParseTreeVisitor visitor) { public final EnrichWithClauseContext enrichWithClause() throws RecognitionException { EnrichWithClauseContext _localctx = new EnrichWithClauseContext(_ctx, getState()); - enterRule(_localctx, 106, RULE_enrichWithClause); + enterRule(_localctx, 108, RULE_enrichWithClause); try { enterOuterAlt(_localctx, 1); { - setState(538); + setState(544); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,52,_ctx) ) { case 1: { - setState(535); + setState(541); ((EnrichWithClauseContext)_localctx).newName = qualifiedNamePattern(); - setState(536); + setState(542); match(ASSIGN); } break; } - setState(540); + setState(546); ((EnrichWithClauseContext)_localctx).enrichField = qualifiedNamePattern(); } } @@ -4884,17 +4979,17 @@ public T accept(ParseTreeVisitor visitor) { public final LookupCommandContext lookupCommand() throws RecognitionException { LookupCommandContext _localctx = new LookupCommandContext(_ctx, getState()); - enterRule(_localctx, 108, RULE_lookupCommand); + enterRule(_localctx, 110, RULE_lookupCommand); try { enterOuterAlt(_localctx, 1); { - setState(542); + setState(548); match(LOOKUP); - setState(543); + setState(549); ((LookupCommandContext)_localctx).tableName = match(INDEX_UNQUOTED_IDENTIFIER); - setState(544); + setState(550); match(ON); - setState(545); + setState(551); ((LookupCommandContext)_localctx).matchFields = qualifiedNamePatterns(); } } @@ -4956,7 +5051,7 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in } public static final String _serializedATN = - "\u0004\u0001{\u0224\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ + "\u0004\u0001|\u022a\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"+ @@ -4970,341 +5065,344 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in "#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007&\u0002\'\u0007\'\u0002"+ "(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007+\u0002,\u0007,\u0002"+ "-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u00070\u00021\u00071\u0002"+ - "2\u00072\u00023\u00073\u00024\u00074\u00025\u00075\u00026\u00076\u0001"+ - "\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0005\u0001x\b\u0001\n\u0001\f\u0001{\t"+ - "\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ - "\u0002\u0003\u0002\u0083\b\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+ + "2\u00072\u00023\u00073\u00024\u00074\u00025\u00075\u00026\u00076\u0002"+ + "7\u00077\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0001z\b\u0001\n\u0001"+ + "\f\u0001}\t\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ + "\u0002\u0001\u0002\u0003\u0002\u0085\b\u0002\u0001\u0003\u0001\u0003\u0001"+ "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+ - "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0003\u0003\u0093"+ - "\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001"+ - "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0003\u0005\u009f"+ - "\b\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0005"+ - "\u0005\u00a6\b\u0005\n\u0005\f\u0005\u00a9\t\u0005\u0001\u0005\u0001\u0005"+ - "\u0001\u0005\u0001\u0005\u0001\u0005\u0003\u0005\u00b0\b\u0005\u0001\u0005"+ - "\u0001\u0005\u0003\u0005\u00b4\b\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ - "\u0001\u0005\u0001\u0005\u0001\u0005\u0005\u0005\u00bc\b\u0005\n\u0005"+ - "\f\u0005\u00bf\t\u0005\u0001\u0006\u0001\u0006\u0003\u0006\u00c3\b\u0006"+ - "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006"+ - "\u00ca\b\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006\u00cf\b"+ - "\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0003"+ - "\u0007\u00d6\b\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0003\b\u00dc\b\b"+ - "\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0005\b\u00e4\b\b\n\b"+ - "\f\b\u00e7\t\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t"+ - "\u0001\t\u0003\t\u00f1\b\t\u0001\t\u0001\t\u0001\t\u0005\t\u00f6\b\t\n"+ - "\t\f\t\u00f9\t\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0005"+ - "\n\u0101\b\n\n\n\f\n\u0104\t\n\u0003\n\u0106\b\n\u0001\n\u0001\n\u0001"+ + "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0003"+ + "\u0003\u0095\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001"+ + "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0003"+ + "\u0005\u00a1\b\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ + "\u0005\u0005\u0005\u00a8\b\u0005\n\u0005\f\u0005\u00ab\t\u0005\u0001\u0005"+ + "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0003\u0005\u00b2\b\u0005"+ + "\u0001\u0005\u0001\u0005\u0003\u0005\u00b6\b\u0005\u0001\u0005\u0001\u0005"+ + "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0005\u0005\u00be\b\u0005"+ + "\n\u0005\f\u0005\u00c1\t\u0005\u0001\u0006\u0001\u0006\u0003\u0006\u00c5"+ + "\b\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003"+ + "\u0006\u00cc\b\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006\u00d1"+ + "\b\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0003"+ + "\u0007\u00d8\b\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0003\b\u00de\b\b"+ + "\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0005\b\u00e6\b\b\n\b"+ + "\f\b\u00e9\t\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t"+ + "\u0001\t\u0003\t\u00f3\b\t\u0001\t\u0001\t\u0001\t\u0005\t\u00f8\b\t\n"+ + "\t\f\t\u00fb\t\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0005"+ + "\n\u0103\b\n\n\n\f\n\u0106\t\n\u0003\n\u0108\b\n\u0001\n\u0001\n\u0001"+ "\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0005"+ - "\r\u0112\b\r\n\r\f\r\u0115\t\r\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+ - "\u000e\u0001\u000e\u0003\u000e\u011c\b\u000e\u0001\u000f\u0001\u000f\u0001"+ - "\u000f\u0001\u000f\u0005\u000f\u0122\b\u000f\n\u000f\f\u000f\u0125\t\u000f"+ - "\u0001\u000f\u0003\u000f\u0128\b\u000f\u0001\u0010\u0001\u0010\u0001\u0011"+ - "\u0001\u0011\u0003\u0011\u012e\b\u0011\u0001\u0012\u0001\u0012\u0001\u0012"+ - "\u0001\u0012\u0005\u0012\u0134\b\u0012\n\u0012\f\u0012\u0137\t\u0012\u0001"+ + "\r\u0114\b\r\n\r\f\r\u0117\t\r\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+ + "\u000e\u0001\u000e\u0003\u000e\u011e\b\u000e\u0001\u000f\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0005\u000f\u0124\b\u000f\n\u000f\f\u000f\u0127\t\u000f"+ + "\u0001\u000f\u0003\u000f\u012a\b\u000f\u0001\u0010\u0001\u0010\u0001\u0011"+ + "\u0001\u0011\u0003\u0011\u0130\b\u0011\u0001\u0012\u0001\u0012\u0001\u0012"+ + "\u0001\u0012\u0005\u0012\u0136\b\u0012\n\u0012\f\u0012\u0139\t\u0012\u0001"+ "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001"+ - "\u0014\u0001\u0014\u0005\u0014\u0141\b\u0014\n\u0014\f\u0014\u0144\t\u0014"+ - "\u0001\u0014\u0003\u0014\u0147\b\u0014\u0001\u0014\u0001\u0014\u0003\u0014"+ - "\u014b\b\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016"+ - "\u0003\u0016\u0152\b\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u0156\b"+ - "\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0003\u0017\u015c"+ - "\b\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0005\u0018\u0161\b\u0018"+ - "\n\u0018\f\u0018\u0164\t\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0005"+ - "\u0019\u0169\b\u0019\n\u0019\f\u0019\u016c\t\u0019\u0001\u001a\u0001\u001a"+ - "\u0001\u001a\u0005\u001a\u0171\b\u001a\n\u001a\f\u001a\u0174\t\u001a\u0001"+ + "\u0014\u0001\u0014\u0005\u0014\u0143\b\u0014\n\u0014\f\u0014\u0146\t\u0014"+ + "\u0001\u0014\u0003\u0014\u0149\b\u0014\u0001\u0014\u0001\u0014\u0003\u0014"+ + "\u014d\b\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016"+ + "\u0003\u0016\u0154\b\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u0158\b"+ + "\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0003\u0017\u015e"+ + "\b\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0005\u0018\u0163\b\u0018"+ + "\n\u0018\f\u0018\u0166\t\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0005"+ + "\u0019\u016b\b\u0019\n\u0019\f\u0019\u016e\t\u0019\u0001\u001a\u0001\u001a"+ + "\u0001\u001a\u0005\u001a\u0173\b\u001a\n\u001a\f\u001a\u0176\t\u001a\u0001"+ "\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001"+ "\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001"+ - "\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0005\u001d\u0187"+ - "\b\u001d\n\u001d\f\u001d\u018a\t\u001d\u0001\u001d\u0001\u001d\u0001\u001d"+ - "\u0001\u001d\u0001\u001d\u0001\u001d\u0005\u001d\u0192\b\u001d\n\u001d"+ - "\f\u001d\u0195\t\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d"+ - "\u0001\u001d\u0001\u001d\u0005\u001d\u019d\b\u001d\n\u001d\f\u001d\u01a0"+ - "\t\u001d\u0001\u001d\u0001\u001d\u0003\u001d\u01a4\b\u001d\u0001\u001e"+ - "\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f"+ - "\u0005\u001f\u01ad\b\u001f\n\u001f\f\u001f\u01b0\t\u001f\u0001 \u0001"+ - " \u0003 \u01b4\b \u0001 \u0001 \u0003 \u01b8\b \u0001!\u0001!\u0001!\u0001"+ - "\"\u0001\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0005#\u01c4\b#\n#\f#\u01c7"+ - "\t#\u0001$\u0001$\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0003%\u01d1"+ - "\b%\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001(\u0001("+ - "\u0001(\u0005(\u01dd\b(\n(\f(\u01e0\t(\u0001)\u0001)\u0001)\u0001)\u0001"+ - "*\u0001*\u0001+\u0001+\u0003+\u01ea\b+\u0001,\u0003,\u01ed\b,\u0001,\u0001"+ - ",\u0001-\u0003-\u01f2\b-\u0001-\u0001-\u0001.\u0001.\u0001/\u0001/\u0001"+ - "0\u00010\u00010\u00011\u00011\u00011\u00011\u00012\u00012\u00012\u0001"+ - "3\u00013\u00013\u00014\u00014\u00014\u00014\u00034\u020b\b4\u00014\u0001"+ - "4\u00014\u00014\u00054\u0211\b4\n4\f4\u0214\t4\u00034\u0216\b4\u00015"+ - "\u00015\u00015\u00035\u021b\b5\u00015\u00015\u00016\u00016\u00016\u0001"+ - "6\u00016\u00016\u0000\u0004\u0002\n\u0010\u00127\u0000\u0002\u0004\u0006"+ - "\b\n\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,."+ - "02468:<>@BDFHJLNPRTVXZ\\^`bdfhjl\u0000\u0007\u0001\u0000?@\u0001\u0000"+ - "AC\u0001\u0000FG\u0002\u0000##\'\'\u0001\u0000*+\u0002\u0000))77\u0002"+ - "\u000088:>\u023e\u0000n\u0001\u0000\u0000\u0000\u0002q\u0001\u0000\u0000"+ - "\u0000\u0004\u0082\u0001\u0000\u0000\u0000\u0006\u0092\u0001\u0000\u0000"+ - "\u0000\b\u0094\u0001\u0000\u0000\u0000\n\u00b3\u0001\u0000\u0000\u0000"+ - "\f\u00ce\u0001\u0000\u0000\u0000\u000e\u00d5\u0001\u0000\u0000\u0000\u0010"+ - "\u00db\u0001\u0000\u0000\u0000\u0012\u00f0\u0001\u0000\u0000\u0000\u0014"+ - "\u00fa\u0001\u0000\u0000\u0000\u0016\u0109\u0001\u0000\u0000\u0000\u0018"+ - "\u010b\u0001\u0000\u0000\u0000\u001a\u010e\u0001\u0000\u0000\u0000\u001c"+ - "\u011b\u0001\u0000\u0000\u0000\u001e\u011d\u0001\u0000\u0000\u0000 \u0129"+ - "\u0001\u0000\u0000\u0000\"\u012d\u0001\u0000\u0000\u0000$\u012f\u0001"+ - "\u0000\u0000\u0000&\u0138\u0001\u0000\u0000\u0000(\u013c\u0001\u0000\u0000"+ - "\u0000*\u014c\u0001\u0000\u0000\u0000,\u014f\u0001\u0000\u0000\u0000."+ - "\u0157\u0001\u0000\u0000\u00000\u015d\u0001\u0000\u0000\u00002\u0165\u0001"+ - "\u0000\u0000\u00004\u016d\u0001\u0000\u0000\u00006\u0175\u0001\u0000\u0000"+ - "\u00008\u0177\u0001\u0000\u0000\u0000:\u01a3\u0001\u0000\u0000\u0000<"+ - "\u01a5\u0001\u0000\u0000\u0000>\u01a8\u0001\u0000\u0000\u0000@\u01b1\u0001"+ - "\u0000\u0000\u0000B\u01b9\u0001\u0000\u0000\u0000D\u01bc\u0001\u0000\u0000"+ - "\u0000F\u01bf\u0001\u0000\u0000\u0000H\u01c8\u0001\u0000\u0000\u0000J"+ - "\u01cc\u0001\u0000\u0000\u0000L\u01d2\u0001\u0000\u0000\u0000N\u01d6\u0001"+ - "\u0000\u0000\u0000P\u01d9\u0001\u0000\u0000\u0000R\u01e1\u0001\u0000\u0000"+ - "\u0000T\u01e5\u0001\u0000\u0000\u0000V\u01e9\u0001\u0000\u0000\u0000X"+ - "\u01ec\u0001\u0000\u0000\u0000Z\u01f1\u0001\u0000\u0000\u0000\\\u01f5"+ - "\u0001\u0000\u0000\u0000^\u01f7\u0001\u0000\u0000\u0000`\u01f9\u0001\u0000"+ - "\u0000\u0000b\u01fc\u0001\u0000\u0000\u0000d\u0200\u0001\u0000\u0000\u0000"+ - "f\u0203\u0001\u0000\u0000\u0000h\u0206\u0001\u0000\u0000\u0000j\u021a"+ - "\u0001\u0000\u0000\u0000l\u021e\u0001\u0000\u0000\u0000no\u0003\u0002"+ - "\u0001\u0000op\u0005\u0000\u0000\u0001p\u0001\u0001\u0000\u0000\u0000"+ - "qr\u0006\u0001\uffff\uffff\u0000rs\u0003\u0004\u0002\u0000sy\u0001\u0000"+ - "\u0000\u0000tu\n\u0001\u0000\u0000uv\u0005\u001d\u0000\u0000vx\u0003\u0006"+ - "\u0003\u0000wt\u0001\u0000\u0000\u0000x{\u0001\u0000\u0000\u0000yw\u0001"+ - "\u0000\u0000\u0000yz\u0001\u0000\u0000\u0000z\u0003\u0001\u0000\u0000"+ - "\u0000{y\u0001\u0000\u0000\u0000|\u0083\u0003`0\u0000}\u0083\u0003\u001e"+ - "\u000f\u0000~\u0083\u0003\u0018\f\u0000\u007f\u0083\u0003(\u0014\u0000"+ - "\u0080\u0083\u0003d2\u0000\u0081\u0083\u0003f3\u0000\u0082|\u0001\u0000"+ - "\u0000\u0000\u0082}\u0001\u0000\u0000\u0000\u0082~\u0001\u0000\u0000\u0000"+ - "\u0082\u007f\u0001\u0000\u0000\u0000\u0082\u0080\u0001\u0000\u0000\u0000"+ - "\u0082\u0081\u0001\u0000\u0000\u0000\u0083\u0005\u0001\u0000\u0000\u0000"+ - "\u0084\u0093\u0003*\u0015\u0000\u0085\u0093\u0003.\u0017\u0000\u0086\u0093"+ - "\u0003<\u001e\u0000\u0087\u0093\u0003l6\u0000\u0088\u0093\u0003B!\u0000"+ - "\u0089\u0093\u0003>\u001f\u0000\u008a\u0093\u0003,\u0016\u0000\u008b\u0093"+ - "\u0003\b\u0004\u0000\u008c\u0093\u0003D\"\u0000\u008d\u0093\u0003F#\u0000"+ - "\u008e\u0093\u0003J%\u0000\u008f\u0093\u0003L&\u0000\u0090\u0093\u0003"+ - "h4\u0000\u0091\u0093\u0003N\'\u0000\u0092\u0084\u0001\u0000\u0000\u0000"+ - "\u0092\u0085\u0001\u0000\u0000\u0000\u0092\u0086\u0001\u0000\u0000\u0000"+ - "\u0092\u0087\u0001\u0000\u0000\u0000\u0092\u0088\u0001\u0000\u0000\u0000"+ - "\u0092\u0089\u0001\u0000\u0000\u0000\u0092\u008a\u0001\u0000\u0000\u0000"+ - "\u0092\u008b\u0001\u0000\u0000\u0000\u0092\u008c\u0001\u0000\u0000\u0000"+ - "\u0092\u008d\u0001\u0000\u0000\u0000\u0092\u008e\u0001\u0000\u0000\u0000"+ - "\u0092\u008f\u0001\u0000\u0000\u0000\u0092\u0090\u0001\u0000\u0000\u0000"+ - "\u0092\u0091\u0001\u0000\u0000\u0000\u0093\u0007\u0001\u0000\u0000\u0000"+ - "\u0094\u0095\u0005\u0014\u0000\u0000\u0095\u0096\u0003\n\u0005\u0000\u0096"+ - "\t\u0001\u0000\u0000\u0000\u0097\u0098\u0006\u0005\uffff\uffff\u0000\u0098"+ - "\u0099\u00050\u0000\u0000\u0099\u00b4\u0003\n\u0005\u0007\u009a\u00b4"+ - "\u0003\u000e\u0007\u0000\u009b\u00b4\u0003\f\u0006\u0000\u009c\u009e\u0003"+ - "\u000e\u0007\u0000\u009d\u009f\u00050\u0000\u0000\u009e\u009d\u0001\u0000"+ - "\u0000\u0000\u009e\u009f\u0001\u0000\u0000\u0000\u009f\u00a0\u0001\u0000"+ - "\u0000\u0000\u00a0\u00a1\u0005-\u0000\u0000\u00a1\u00a2\u0005,\u0000\u0000"+ - "\u00a2\u00a7\u0003\u000e\u0007\u0000\u00a3\u00a4\u0005&\u0000\u0000\u00a4"+ - "\u00a6\u0003\u000e\u0007\u0000\u00a5\u00a3\u0001\u0000\u0000\u0000\u00a6"+ - "\u00a9\u0001\u0000\u0000\u0000\u00a7\u00a5\u0001\u0000\u0000\u0000\u00a7"+ - "\u00a8\u0001\u0000\u0000\u0000\u00a8\u00aa\u0001\u0000\u0000\u0000\u00a9"+ - "\u00a7\u0001\u0000\u0000\u0000\u00aa\u00ab\u00056\u0000\u0000\u00ab\u00b4"+ - "\u0001\u0000\u0000\u0000\u00ac\u00ad\u0003\u000e\u0007\u0000\u00ad\u00af"+ - "\u0005.\u0000\u0000\u00ae\u00b0\u00050\u0000\u0000\u00af\u00ae\u0001\u0000"+ - "\u0000\u0000\u00af\u00b0\u0001\u0000\u0000\u0000\u00b0\u00b1\u0001\u0000"+ - "\u0000\u0000\u00b1\u00b2\u00051\u0000\u0000\u00b2\u00b4\u0001\u0000\u0000"+ - "\u0000\u00b3\u0097\u0001\u0000\u0000\u0000\u00b3\u009a\u0001\u0000\u0000"+ - "\u0000\u00b3\u009b\u0001\u0000\u0000\u0000\u00b3\u009c\u0001\u0000\u0000"+ - "\u0000\u00b3\u00ac\u0001\u0000\u0000\u0000\u00b4\u00bd\u0001\u0000\u0000"+ - "\u0000\u00b5\u00b6\n\u0004\u0000\u0000\u00b6\u00b7\u0005\"\u0000\u0000"+ - "\u00b7\u00bc\u0003\n\u0005\u0005\u00b8\u00b9\n\u0003\u0000\u0000\u00b9"+ - "\u00ba\u00053\u0000\u0000\u00ba\u00bc\u0003\n\u0005\u0004\u00bb\u00b5"+ - "\u0001\u0000\u0000\u0000\u00bb\u00b8\u0001\u0000\u0000\u0000\u00bc\u00bf"+ - "\u0001\u0000\u0000\u0000\u00bd\u00bb\u0001\u0000\u0000\u0000\u00bd\u00be"+ - "\u0001\u0000\u0000\u0000\u00be\u000b\u0001\u0000\u0000\u0000\u00bf\u00bd"+ - "\u0001\u0000\u0000\u0000\u00c0\u00c2\u0003\u000e\u0007\u0000\u00c1\u00c3"+ - "\u00050\u0000\u0000\u00c2\u00c1\u0001\u0000\u0000\u0000\u00c2\u00c3\u0001"+ - "\u0000\u0000\u0000\u00c3\u00c4\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005"+ - "/\u0000\u0000\u00c5\u00c6\u0003\\.\u0000\u00c6\u00cf\u0001\u0000\u0000"+ - "\u0000\u00c7\u00c9\u0003\u000e\u0007\u0000\u00c8\u00ca\u00050\u0000\u0000"+ - "\u00c9\u00c8\u0001\u0000\u0000\u0000\u00c9\u00ca\u0001\u0000\u0000\u0000"+ - "\u00ca\u00cb\u0001\u0000\u0000\u0000\u00cb\u00cc\u00055\u0000\u0000\u00cc"+ - "\u00cd\u0003\\.\u0000\u00cd\u00cf\u0001\u0000\u0000\u0000\u00ce\u00c0"+ - "\u0001\u0000\u0000\u0000\u00ce\u00c7\u0001\u0000\u0000\u0000\u00cf\r\u0001"+ - "\u0000\u0000\u0000\u00d0\u00d6\u0003\u0010\b\u0000\u00d1\u00d2\u0003\u0010"+ - "\b\u0000\u00d2\u00d3\u0003^/\u0000\u00d3\u00d4\u0003\u0010\b\u0000\u00d4"+ - "\u00d6\u0001\u0000\u0000\u0000\u00d5\u00d0\u0001\u0000\u0000\u0000\u00d5"+ - "\u00d1\u0001\u0000\u0000\u0000\u00d6\u000f\u0001\u0000\u0000\u0000\u00d7"+ - "\u00d8\u0006\b\uffff\uffff\u0000\u00d8\u00dc\u0003\u0012\t\u0000\u00d9"+ - "\u00da\u0007\u0000\u0000\u0000\u00da\u00dc\u0003\u0010\b\u0003\u00db\u00d7"+ - "\u0001\u0000\u0000\u0000\u00db\u00d9\u0001\u0000\u0000\u0000\u00dc\u00e5"+ - "\u0001\u0000\u0000\u0000\u00dd\u00de\n\u0002\u0000\u0000\u00de\u00df\u0007"+ - "\u0001\u0000\u0000\u00df\u00e4\u0003\u0010\b\u0003\u00e0\u00e1\n\u0001"+ - "\u0000\u0000\u00e1\u00e2\u0007\u0000\u0000\u0000\u00e2\u00e4\u0003\u0010"+ - "\b\u0002\u00e3\u00dd\u0001\u0000\u0000\u0000\u00e3\u00e0\u0001\u0000\u0000"+ - "\u0000\u00e4\u00e7\u0001\u0000\u0000\u0000\u00e5\u00e3\u0001\u0000\u0000"+ - "\u0000\u00e5\u00e6\u0001\u0000\u0000\u0000\u00e6\u0011\u0001\u0000\u0000"+ - "\u0000\u00e7\u00e5\u0001\u0000\u0000\u0000\u00e8\u00e9\u0006\t\uffff\uffff"+ - "\u0000\u00e9\u00f1\u0003:\u001d\u0000\u00ea\u00f1\u00030\u0018\u0000\u00eb"+ - "\u00f1\u0003\u0014\n\u0000\u00ec\u00ed\u0005,\u0000\u0000\u00ed\u00ee"+ - "\u0003\n\u0005\u0000\u00ee\u00ef\u00056\u0000\u0000\u00ef\u00f1\u0001"+ - "\u0000\u0000\u0000\u00f0\u00e8\u0001\u0000\u0000\u0000\u00f0\u00ea\u0001"+ - "\u0000\u0000\u0000\u00f0\u00eb\u0001\u0000\u0000\u0000\u00f0\u00ec\u0001"+ - "\u0000\u0000\u0000\u00f1\u00f7\u0001\u0000\u0000\u0000\u00f2\u00f3\n\u0001"+ - "\u0000\u0000\u00f3\u00f4\u0005%\u0000\u0000\u00f4\u00f6\u0003\u0016\u000b"+ - "\u0000\u00f5\u00f2\u0001\u0000\u0000\u0000\u00f6\u00f9\u0001\u0000\u0000"+ - "\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000\u00f7\u00f8\u0001\u0000\u0000"+ - "\u0000\u00f8\u0013\u0001\u0000\u0000\u0000\u00f9\u00f7\u0001\u0000\u0000"+ - "\u0000\u00fa\u00fb\u00036\u001b\u0000\u00fb\u0105\u0005,\u0000\u0000\u00fc"+ - "\u0106\u0005A\u0000\u0000\u00fd\u0102\u0003\n\u0005\u0000\u00fe\u00ff"+ - "\u0005&\u0000\u0000\u00ff\u0101\u0003\n\u0005\u0000\u0100\u00fe\u0001"+ - "\u0000\u0000\u0000\u0101\u0104\u0001\u0000\u0000\u0000\u0102\u0100\u0001"+ - "\u0000\u0000\u0000\u0102\u0103\u0001\u0000\u0000\u0000\u0103\u0106\u0001"+ - "\u0000\u0000\u0000\u0104\u0102\u0001\u0000\u0000\u0000\u0105\u00fc\u0001"+ - "\u0000\u0000\u0000\u0105\u00fd\u0001\u0000\u0000\u0000\u0105\u0106\u0001"+ - "\u0000\u0000\u0000\u0106\u0107\u0001\u0000\u0000\u0000\u0107\u0108\u0005"+ - "6\u0000\u0000\u0108\u0015\u0001\u0000\u0000\u0000\u0109\u010a\u00036\u001b"+ - "\u0000\u010a\u0017\u0001\u0000\u0000\u0000\u010b\u010c\u0005\u0010\u0000"+ - "\u0000\u010c\u010d\u0003\u001a\r\u0000\u010d\u0019\u0001\u0000\u0000\u0000"+ - "\u010e\u0113\u0003\u001c\u000e\u0000\u010f\u0110\u0005&\u0000\u0000\u0110"+ - "\u0112\u0003\u001c\u000e\u0000\u0111\u010f\u0001\u0000\u0000\u0000\u0112"+ - "\u0115\u0001\u0000\u0000\u0000\u0113\u0111\u0001\u0000\u0000\u0000\u0113"+ - "\u0114\u0001\u0000\u0000\u0000\u0114\u001b\u0001\u0000\u0000\u0000\u0115"+ - "\u0113\u0001\u0000\u0000\u0000\u0116\u011c\u0003\n\u0005\u0000\u0117\u0118"+ - "\u00030\u0018\u0000\u0118\u0119\u0005$\u0000\u0000\u0119\u011a\u0003\n"+ - "\u0005\u0000\u011a\u011c\u0001\u0000\u0000\u0000\u011b\u0116\u0001\u0000"+ - "\u0000\u0000\u011b\u0117\u0001\u0000\u0000\u0000\u011c\u001d\u0001\u0000"+ - "\u0000\u0000\u011d\u011e\u0005\u0006\u0000\u0000\u011e\u0123\u0003 \u0010"+ - "\u0000\u011f\u0120\u0005&\u0000\u0000\u0120\u0122\u0003 \u0010\u0000\u0121"+ - "\u011f\u0001\u0000\u0000\u0000\u0122\u0125\u0001\u0000\u0000\u0000\u0123"+ - "\u0121\u0001\u0000\u0000\u0000\u0123\u0124\u0001\u0000\u0000\u0000\u0124"+ - "\u0127\u0001\u0000\u0000\u0000\u0125\u0123\u0001\u0000\u0000\u0000\u0126"+ - "\u0128\u0003\"\u0011\u0000\u0127\u0126\u0001\u0000\u0000\u0000\u0127\u0128"+ - "\u0001\u0000\u0000\u0000\u0128\u001f\u0001\u0000\u0000\u0000\u0129\u012a"+ - "\u0005\u0019\u0000\u0000\u012a!\u0001\u0000\u0000\u0000\u012b\u012e\u0003"+ - "$\u0012\u0000\u012c\u012e\u0003&\u0013\u0000\u012d\u012b\u0001\u0000\u0000"+ - "\u0000\u012d\u012c\u0001\u0000\u0000\u0000\u012e#\u0001\u0000\u0000\u0000"+ - "\u012f\u0130\u0005K\u0000\u0000\u0130\u0135\u0003 \u0010\u0000\u0131\u0132"+ - "\u0005&\u0000\u0000\u0132\u0134\u0003 \u0010\u0000\u0133\u0131\u0001\u0000"+ - "\u0000\u0000\u0134\u0137\u0001\u0000\u0000\u0000\u0135\u0133\u0001\u0000"+ - "\u0000\u0000\u0135\u0136\u0001\u0000\u0000\u0000\u0136%\u0001\u0000\u0000"+ - "\u0000\u0137\u0135\u0001\u0000\u0000\u0000\u0138\u0139\u0005D\u0000\u0000"+ - "\u0139\u013a\u0003$\u0012\u0000\u013a\u013b\u0005E\u0000\u0000\u013b\'"+ - "\u0001\u0000\u0000\u0000\u013c\u013d\u0005\r\u0000\u0000\u013d\u0142\u0003"+ - " \u0010\u0000\u013e\u013f\u0005&\u0000\u0000\u013f\u0141\u0003 \u0010"+ - "\u0000\u0140\u013e\u0001\u0000\u0000\u0000\u0141\u0144\u0001\u0000\u0000"+ - "\u0000\u0142\u0140\u0001\u0000\u0000\u0000\u0142\u0143\u0001\u0000\u0000"+ - "\u0000\u0143\u0146\u0001\u0000\u0000\u0000\u0144\u0142\u0001\u0000\u0000"+ - "\u0000\u0145\u0147\u0003\u001a\r\u0000\u0146\u0145\u0001\u0000\u0000\u0000"+ - "\u0146\u0147\u0001\u0000\u0000\u0000\u0147\u014a\u0001\u0000\u0000\u0000"+ - "\u0148\u0149\u0005!\u0000\u0000\u0149\u014b\u0003\u001a\r\u0000\u014a"+ - "\u0148\u0001\u0000\u0000\u0000\u014a\u014b\u0001\u0000\u0000\u0000\u014b"+ - ")\u0001\u0000\u0000\u0000\u014c\u014d\u0005\u0004\u0000\u0000\u014d\u014e"+ - "\u0003\u001a\r\u0000\u014e+\u0001\u0000\u0000\u0000\u014f\u0151\u0005"+ - "\u0013\u0000\u0000\u0150\u0152\u0003\u001a\r\u0000\u0151\u0150\u0001\u0000"+ - "\u0000\u0000\u0151\u0152\u0001\u0000\u0000\u0000\u0152\u0155\u0001\u0000"+ - "\u0000\u0000\u0153\u0154\u0005!\u0000\u0000\u0154\u0156\u0003\u001a\r"+ - "\u0000\u0155\u0153\u0001\u0000\u0000\u0000\u0155\u0156\u0001\u0000\u0000"+ - "\u0000\u0156-\u0001\u0000\u0000\u0000\u0157\u0158\u0005\b\u0000\u0000"+ - "\u0158\u015b\u0003\u001a\r\u0000\u0159\u015a\u0005!\u0000\u0000\u015a"+ - "\u015c\u0003\u001a\r\u0000\u015b\u0159\u0001\u0000\u0000\u0000\u015b\u015c"+ - "\u0001\u0000\u0000\u0000\u015c/\u0001\u0000\u0000\u0000\u015d\u0162\u0003"+ - "6\u001b\u0000\u015e\u015f\u0005(\u0000\u0000\u015f\u0161\u00036\u001b"+ - "\u0000\u0160\u015e\u0001\u0000\u0000\u0000\u0161\u0164\u0001\u0000\u0000"+ - "\u0000\u0162\u0160\u0001\u0000\u0000\u0000\u0162\u0163\u0001\u0000\u0000"+ - "\u0000\u01631\u0001\u0000\u0000\u0000\u0164\u0162\u0001\u0000\u0000\u0000"+ - "\u0165\u016a\u00038\u001c\u0000\u0166\u0167\u0005(\u0000\u0000\u0167\u0169"+ - "\u00038\u001c\u0000\u0168\u0166\u0001\u0000\u0000\u0000\u0169\u016c\u0001"+ - "\u0000\u0000\u0000\u016a\u0168\u0001\u0000\u0000\u0000\u016a\u016b\u0001"+ - "\u0000\u0000\u0000\u016b3\u0001\u0000\u0000\u0000\u016c\u016a\u0001\u0000"+ - "\u0000\u0000\u016d\u0172\u00032\u0019\u0000\u016e\u016f\u0005&\u0000\u0000"+ - "\u016f\u0171\u00032\u0019\u0000\u0170\u016e\u0001\u0000\u0000\u0000\u0171"+ - "\u0174\u0001\u0000\u0000\u0000\u0172\u0170\u0001\u0000\u0000\u0000\u0172"+ - "\u0173\u0001\u0000\u0000\u0000\u01735\u0001\u0000\u0000\u0000\u0174\u0172"+ - "\u0001\u0000\u0000\u0000\u0175\u0176\u0007\u0002\u0000\u0000\u01767\u0001"+ - "\u0000\u0000\u0000\u0177\u0178\u0005O\u0000\u0000\u01789\u0001\u0000\u0000"+ - "\u0000\u0179\u01a4\u00051\u0000\u0000\u017a\u017b\u0003Z-\u0000\u017b"+ - "\u017c\u0005F\u0000\u0000\u017c\u01a4\u0001\u0000\u0000\u0000\u017d\u01a4"+ - "\u0003X,\u0000\u017e\u01a4\u0003Z-\u0000\u017f\u01a4\u0003T*\u0000\u0180"+ - "\u01a4\u00054\u0000\u0000\u0181\u01a4\u0003\\.\u0000\u0182\u0183\u0005"+ - "D\u0000\u0000\u0183\u0188\u0003V+\u0000\u0184\u0185\u0005&\u0000\u0000"+ - "\u0185\u0187\u0003V+\u0000\u0186\u0184\u0001\u0000\u0000\u0000\u0187\u018a"+ - "\u0001\u0000\u0000\u0000\u0188\u0186\u0001\u0000\u0000\u0000\u0188\u0189"+ - "\u0001\u0000\u0000\u0000\u0189\u018b\u0001\u0000\u0000\u0000\u018a\u0188"+ - "\u0001\u0000\u0000\u0000\u018b\u018c\u0005E\u0000\u0000\u018c\u01a4\u0001"+ - "\u0000\u0000\u0000\u018d\u018e\u0005D\u0000\u0000\u018e\u0193\u0003T*"+ - "\u0000\u018f\u0190\u0005&\u0000\u0000\u0190\u0192\u0003T*\u0000\u0191"+ - "\u018f\u0001\u0000\u0000\u0000\u0192\u0195\u0001\u0000\u0000\u0000\u0193"+ - "\u0191\u0001\u0000\u0000\u0000\u0193\u0194\u0001\u0000\u0000\u0000\u0194"+ - "\u0196\u0001\u0000\u0000\u0000\u0195\u0193\u0001\u0000\u0000\u0000\u0196"+ - "\u0197\u0005E\u0000\u0000\u0197\u01a4\u0001\u0000\u0000\u0000\u0198\u0199"+ - "\u0005D\u0000\u0000\u0199\u019e\u0003\\.\u0000\u019a\u019b\u0005&\u0000"+ - "\u0000\u019b\u019d\u0003\\.\u0000\u019c\u019a\u0001\u0000\u0000\u0000"+ - "\u019d\u01a0\u0001\u0000\u0000\u0000\u019e\u019c\u0001\u0000\u0000\u0000"+ - "\u019e\u019f\u0001\u0000\u0000\u0000\u019f\u01a1\u0001\u0000\u0000\u0000"+ - "\u01a0\u019e\u0001\u0000\u0000\u0000\u01a1\u01a2\u0005E\u0000\u0000\u01a2"+ - "\u01a4\u0001\u0000\u0000\u0000\u01a3\u0179\u0001\u0000\u0000\u0000\u01a3"+ - "\u017a\u0001\u0000\u0000\u0000\u01a3\u017d\u0001\u0000\u0000\u0000\u01a3"+ - "\u017e\u0001\u0000\u0000\u0000\u01a3\u017f\u0001\u0000\u0000\u0000\u01a3"+ - "\u0180\u0001\u0000\u0000\u0000\u01a3\u0181\u0001\u0000\u0000\u0000\u01a3"+ - "\u0182\u0001\u0000\u0000\u0000\u01a3\u018d\u0001\u0000\u0000\u0000\u01a3"+ - "\u0198\u0001\u0000\u0000\u0000\u01a4;\u0001\u0000\u0000\u0000\u01a5\u01a6"+ - "\u0005\n\u0000\u0000\u01a6\u01a7\u0005\u001f\u0000\u0000\u01a7=\u0001"+ - "\u0000\u0000\u0000\u01a8\u01a9\u0005\u0012\u0000\u0000\u01a9\u01ae\u0003"+ - "@ \u0000\u01aa\u01ab\u0005&\u0000\u0000\u01ab\u01ad\u0003@ \u0000\u01ac"+ - "\u01aa\u0001\u0000\u0000\u0000\u01ad\u01b0\u0001\u0000\u0000\u0000\u01ae"+ - "\u01ac\u0001\u0000\u0000\u0000\u01ae\u01af\u0001\u0000\u0000\u0000\u01af"+ - "?\u0001\u0000\u0000\u0000\u01b0\u01ae\u0001\u0000\u0000\u0000\u01b1\u01b3"+ - "\u0003\n\u0005\u0000\u01b2\u01b4\u0007\u0003\u0000\u0000\u01b3\u01b2\u0001"+ - "\u0000\u0000\u0000\u01b3\u01b4\u0001\u0000\u0000\u0000\u01b4\u01b7\u0001"+ - "\u0000\u0000\u0000\u01b5\u01b6\u00052\u0000\u0000\u01b6\u01b8\u0007\u0004"+ - "\u0000\u0000\u01b7\u01b5\u0001\u0000\u0000\u0000\u01b7\u01b8\u0001\u0000"+ - "\u0000\u0000\u01b8A\u0001\u0000\u0000\u0000\u01b9\u01ba\u0005\t\u0000"+ - "\u0000\u01ba\u01bb\u00034\u001a\u0000\u01bbC\u0001\u0000\u0000\u0000\u01bc"+ - "\u01bd\u0005\u0002\u0000\u0000\u01bd\u01be\u00034\u001a\u0000\u01beE\u0001"+ - "\u0000\u0000\u0000\u01bf\u01c0\u0005\u000f\u0000\u0000\u01c0\u01c5\u0003"+ - "H$\u0000\u01c1\u01c2\u0005&\u0000\u0000\u01c2\u01c4\u0003H$\u0000\u01c3"+ - "\u01c1\u0001\u0000\u0000\u0000\u01c4\u01c7\u0001\u0000\u0000\u0000\u01c5"+ - "\u01c3\u0001\u0000\u0000\u0000\u01c5\u01c6\u0001\u0000\u0000\u0000\u01c6"+ - "G\u0001\u0000\u0000\u0000\u01c7\u01c5\u0001\u0000\u0000\u0000\u01c8\u01c9"+ - "\u00032\u0019\u0000\u01c9\u01ca\u0005S\u0000\u0000\u01ca\u01cb\u00032"+ - "\u0019\u0000\u01cbI\u0001\u0000\u0000\u0000\u01cc\u01cd\u0005\u0001\u0000"+ - "\u0000\u01cd\u01ce\u0003\u0012\t\u0000\u01ce\u01d0\u0003\\.\u0000\u01cf"+ - "\u01d1\u0003P(\u0000\u01d0\u01cf\u0001\u0000\u0000\u0000\u01d0\u01d1\u0001"+ - "\u0000\u0000\u0000\u01d1K\u0001\u0000\u0000\u0000\u01d2\u01d3\u0005\u0007"+ - "\u0000\u0000\u01d3\u01d4\u0003\u0012\t\u0000\u01d4\u01d5\u0003\\.\u0000"+ - "\u01d5M\u0001\u0000\u0000\u0000\u01d6\u01d7\u0005\u000e\u0000\u0000\u01d7"+ - "\u01d8\u00030\u0018\u0000\u01d8O\u0001\u0000\u0000\u0000\u01d9\u01de\u0003"+ - "R)\u0000\u01da\u01db\u0005&\u0000\u0000\u01db\u01dd\u0003R)\u0000\u01dc"+ - "\u01da\u0001\u0000\u0000\u0000\u01dd\u01e0\u0001\u0000\u0000\u0000\u01de"+ - "\u01dc\u0001\u0000\u0000\u0000\u01de\u01df\u0001\u0000\u0000\u0000\u01df"+ - "Q\u0001\u0000\u0000\u0000\u01e0\u01de\u0001\u0000\u0000\u0000\u01e1\u01e2"+ - "\u00036\u001b\u0000\u01e2\u01e3\u0005$\u0000\u0000\u01e3\u01e4\u0003:"+ - "\u001d\u0000\u01e4S\u0001\u0000\u0000\u0000\u01e5\u01e6\u0007\u0005\u0000"+ - "\u0000\u01e6U\u0001\u0000\u0000\u0000\u01e7\u01ea\u0003X,\u0000\u01e8"+ - "\u01ea\u0003Z-\u0000\u01e9\u01e7\u0001\u0000\u0000\u0000\u01e9\u01e8\u0001"+ - "\u0000\u0000\u0000\u01eaW\u0001\u0000\u0000\u0000\u01eb\u01ed\u0007\u0000"+ - "\u0000\u0000\u01ec\u01eb\u0001\u0000\u0000\u0000\u01ec\u01ed\u0001\u0000"+ - "\u0000\u0000\u01ed\u01ee\u0001\u0000\u0000\u0000\u01ee\u01ef\u0005 \u0000"+ - "\u0000\u01efY\u0001\u0000\u0000\u0000\u01f0\u01f2\u0007\u0000\u0000\u0000"+ - "\u01f1\u01f0\u0001\u0000\u0000\u0000\u01f1\u01f2\u0001\u0000\u0000\u0000"+ - "\u01f2\u01f3\u0001\u0000\u0000\u0000\u01f3\u01f4\u0005\u001f\u0000\u0000"+ - "\u01f4[\u0001\u0000\u0000\u0000\u01f5\u01f6\u0005\u001e\u0000\u0000\u01f6"+ - "]\u0001\u0000\u0000\u0000\u01f7\u01f8\u0007\u0006\u0000\u0000\u01f8_\u0001"+ - "\u0000\u0000\u0000\u01f9\u01fa\u0005\u0005\u0000\u0000\u01fa\u01fb\u0003"+ - "b1\u0000\u01fba\u0001\u0000\u0000\u0000\u01fc\u01fd\u0005D\u0000\u0000"+ - "\u01fd\u01fe\u0003\u0002\u0001\u0000\u01fe\u01ff\u0005E\u0000\u0000\u01ff"+ - "c\u0001\u0000\u0000\u0000\u0200\u0201\u0005\u0011\u0000\u0000\u0201\u0202"+ - "\u0005i\u0000\u0000\u0202e\u0001\u0000\u0000\u0000\u0203\u0204\u0005\f"+ - "\u0000\u0000\u0204\u0205\u0005m\u0000\u0000\u0205g\u0001\u0000\u0000\u0000"+ - "\u0206\u0207\u0005\u0003\u0000\u0000\u0207\u020a\u0005Y\u0000\u0000\u0208"+ - "\u0209\u0005W\u0000\u0000\u0209\u020b\u00032\u0019\u0000\u020a\u0208\u0001"+ - "\u0000\u0000\u0000\u020a\u020b\u0001\u0000\u0000\u0000\u020b\u0215\u0001"+ - "\u0000\u0000\u0000\u020c\u020d\u0005X\u0000\u0000\u020d\u0212\u0003j5"+ - "\u0000\u020e\u020f\u0005&\u0000\u0000\u020f\u0211\u0003j5\u0000\u0210"+ - "\u020e\u0001\u0000\u0000\u0000\u0211\u0214\u0001\u0000\u0000\u0000\u0212"+ - "\u0210\u0001\u0000\u0000\u0000\u0212\u0213\u0001\u0000\u0000\u0000\u0213"+ - "\u0216\u0001\u0000\u0000\u0000\u0214\u0212\u0001\u0000\u0000\u0000\u0215"+ - "\u020c\u0001\u0000\u0000\u0000\u0215\u0216\u0001\u0000\u0000\u0000\u0216"+ - "i\u0001\u0000\u0000\u0000\u0217\u0218\u00032\u0019\u0000\u0218\u0219\u0005"+ - "$\u0000\u0000\u0219\u021b\u0001\u0000\u0000\u0000\u021a\u0217\u0001\u0000"+ - "\u0000\u0000\u021a\u021b\u0001\u0000\u0000\u0000\u021b\u021c\u0001\u0000"+ - "\u0000\u0000\u021c\u021d\u00032\u0019\u0000\u021dk\u0001\u0000\u0000\u0000"+ - "\u021e\u021f\u0005\u000b\u0000\u0000\u021f\u0220\u0005\u0019\u0000\u0000"+ - "\u0220\u0221\u0005W\u0000\u0000\u0221\u0222\u00034\u001a\u0000\u0222m"+ - "\u0001\u0000\u0000\u00004y\u0082\u0092\u009e\u00a7\u00af\u00b3\u00bb\u00bd"+ - "\u00c2\u00c9\u00ce\u00d5\u00db\u00e3\u00e5\u00f0\u00f7\u0102\u0105\u0113"+ - "\u011b\u0123\u0127\u012d\u0135\u0142\u0146\u014a\u0151\u0155\u015b\u0162"+ - "\u016a\u0172\u0188\u0193\u019e\u01a3\u01ae\u01b3\u01b7\u01c5\u01d0\u01de"+ - "\u01e9\u01ec\u01f1\u020a\u0212\u0215\u021a"; + "\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0005\u001d\u0189"+ + "\b\u001d\n\u001d\f\u001d\u018c\t\u001d\u0001\u001d\u0001\u001d\u0001\u001d"+ + "\u0001\u001d\u0001\u001d\u0001\u001d\u0005\u001d\u0194\b\u001d\n\u001d"+ + "\f\u001d\u0197\t\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d"+ + "\u0001\u001d\u0001\u001d\u0005\u001d\u019f\b\u001d\n\u001d\f\u001d\u01a2"+ + "\t\u001d\u0001\u001d\u0001\u001d\u0003\u001d\u01a6\b\u001d\u0001\u001e"+ + "\u0001\u001e\u0003\u001e\u01aa\b\u001e\u0001\u001f\u0001\u001f\u0001\u001f"+ + "\u0001 \u0001 \u0001 \u0001 \u0005 \u01b3\b \n \f \u01b6\t \u0001!\u0001"+ + "!\u0003!\u01ba\b!\u0001!\u0001!\u0003!\u01be\b!\u0001\"\u0001\"\u0001"+ + "\"\u0001#\u0001#\u0001#\u0001$\u0001$\u0001$\u0001$\u0005$\u01ca\b$\n"+ + "$\f$\u01cd\t$\u0001%\u0001%\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&"+ + "\u0003&\u01d7\b&\u0001\'\u0001\'\u0001\'\u0001\'\u0001(\u0001(\u0001("+ + "\u0001)\u0001)\u0001)\u0005)\u01e3\b)\n)\f)\u01e6\t)\u0001*\u0001*\u0001"+ + "*\u0001*\u0001+\u0001+\u0001,\u0001,\u0003,\u01f0\b,\u0001-\u0003-\u01f3"+ + "\b-\u0001-\u0001-\u0001.\u0003.\u01f8\b.\u0001.\u0001.\u0001/\u0001/\u0001"+ + "0\u00010\u00011\u00011\u00011\u00012\u00012\u00012\u00012\u00013\u0001"+ + "3\u00013\u00014\u00014\u00014\u00015\u00015\u00015\u00015\u00035\u0211"+ + "\b5\u00015\u00015\u00015\u00015\u00055\u0217\b5\n5\f5\u021a\t5\u00035"+ + "\u021c\b5\u00016\u00016\u00016\u00036\u0221\b6\u00016\u00016\u00017\u0001"+ + "7\u00017\u00017\u00017\u00017\u0000\u0004\u0002\n\u0010\u00128\u0000\u0002"+ + "\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e"+ + " \"$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfhjln\u0000\u0007\u0001\u0000?@\u0001"+ + "\u0000AC\u0001\u0000GH\u0002\u0000##\'\'\u0001\u0000*+\u0002\u0000))7"+ + "7\u0002\u000088:>\u0244\u0000p\u0001\u0000\u0000\u0000\u0002s\u0001\u0000"+ + "\u0000\u0000\u0004\u0084\u0001\u0000\u0000\u0000\u0006\u0094\u0001\u0000"+ + "\u0000\u0000\b\u0096\u0001\u0000\u0000\u0000\n\u00b5\u0001\u0000\u0000"+ + "\u0000\f\u00d0\u0001\u0000\u0000\u0000\u000e\u00d7\u0001\u0000\u0000\u0000"+ + "\u0010\u00dd\u0001\u0000\u0000\u0000\u0012\u00f2\u0001\u0000\u0000\u0000"+ + "\u0014\u00fc\u0001\u0000\u0000\u0000\u0016\u010b\u0001\u0000\u0000\u0000"+ + "\u0018\u010d\u0001\u0000\u0000\u0000\u001a\u0110\u0001\u0000\u0000\u0000"+ + "\u001c\u011d\u0001\u0000\u0000\u0000\u001e\u011f\u0001\u0000\u0000\u0000"+ + " \u012b\u0001\u0000\u0000\u0000\"\u012f\u0001\u0000\u0000\u0000$\u0131"+ + "\u0001\u0000\u0000\u0000&\u013a\u0001\u0000\u0000\u0000(\u013e\u0001\u0000"+ + "\u0000\u0000*\u014e\u0001\u0000\u0000\u0000,\u0151\u0001\u0000\u0000\u0000"+ + ".\u0159\u0001\u0000\u0000\u00000\u015f\u0001\u0000\u0000\u00002\u0167"+ + "\u0001\u0000\u0000\u00004\u016f\u0001\u0000\u0000\u00006\u0177\u0001\u0000"+ + "\u0000\u00008\u0179\u0001\u0000\u0000\u0000:\u01a5\u0001\u0000\u0000\u0000"+ + "<\u01a9\u0001\u0000\u0000\u0000>\u01ab\u0001\u0000\u0000\u0000@\u01ae"+ + "\u0001\u0000\u0000\u0000B\u01b7\u0001\u0000\u0000\u0000D\u01bf\u0001\u0000"+ + "\u0000\u0000F\u01c2\u0001\u0000\u0000\u0000H\u01c5\u0001\u0000\u0000\u0000"+ + "J\u01ce\u0001\u0000\u0000\u0000L\u01d2\u0001\u0000\u0000\u0000N\u01d8"+ + "\u0001\u0000\u0000\u0000P\u01dc\u0001\u0000\u0000\u0000R\u01df\u0001\u0000"+ + "\u0000\u0000T\u01e7\u0001\u0000\u0000\u0000V\u01eb\u0001\u0000\u0000\u0000"+ + "X\u01ef\u0001\u0000\u0000\u0000Z\u01f2\u0001\u0000\u0000\u0000\\\u01f7"+ + "\u0001\u0000\u0000\u0000^\u01fb\u0001\u0000\u0000\u0000`\u01fd\u0001\u0000"+ + "\u0000\u0000b\u01ff\u0001\u0000\u0000\u0000d\u0202\u0001\u0000\u0000\u0000"+ + "f\u0206\u0001\u0000\u0000\u0000h\u0209\u0001\u0000\u0000\u0000j\u020c"+ + "\u0001\u0000\u0000\u0000l\u0220\u0001\u0000\u0000\u0000n\u0224\u0001\u0000"+ + "\u0000\u0000pq\u0003\u0002\u0001\u0000qr\u0005\u0000\u0000\u0001r\u0001"+ + "\u0001\u0000\u0000\u0000st\u0006\u0001\uffff\uffff\u0000tu\u0003\u0004"+ + "\u0002\u0000u{\u0001\u0000\u0000\u0000vw\n\u0001\u0000\u0000wx\u0005\u001d"+ + "\u0000\u0000xz\u0003\u0006\u0003\u0000yv\u0001\u0000\u0000\u0000z}\u0001"+ + "\u0000\u0000\u0000{y\u0001\u0000\u0000\u0000{|\u0001\u0000\u0000\u0000"+ + "|\u0003\u0001\u0000\u0000\u0000}{\u0001\u0000\u0000\u0000~\u0085\u0003"+ + "b1\u0000\u007f\u0085\u0003\u001e\u000f\u0000\u0080\u0085\u0003\u0018\f"+ + "\u0000\u0081\u0085\u0003(\u0014\u0000\u0082\u0085\u0003f3\u0000\u0083"+ + "\u0085\u0003h4\u0000\u0084~\u0001\u0000\u0000\u0000\u0084\u007f\u0001"+ + "\u0000\u0000\u0000\u0084\u0080\u0001\u0000\u0000\u0000\u0084\u0081\u0001"+ + "\u0000\u0000\u0000\u0084\u0082\u0001\u0000\u0000\u0000\u0084\u0083\u0001"+ + "\u0000\u0000\u0000\u0085\u0005\u0001\u0000\u0000\u0000\u0086\u0095\u0003"+ + "*\u0015\u0000\u0087\u0095\u0003.\u0017\u0000\u0088\u0095\u0003>\u001f"+ + "\u0000\u0089\u0095\u0003n7\u0000\u008a\u0095\u0003D\"\u0000\u008b\u0095"+ + "\u0003@ \u0000\u008c\u0095\u0003,\u0016\u0000\u008d\u0095\u0003\b\u0004"+ + "\u0000\u008e\u0095\u0003F#\u0000\u008f\u0095\u0003H$\u0000\u0090\u0095"+ + "\u0003L&\u0000\u0091\u0095\u0003N\'\u0000\u0092\u0095\u0003j5\u0000\u0093"+ + "\u0095\u0003P(\u0000\u0094\u0086\u0001\u0000\u0000\u0000\u0094\u0087\u0001"+ + "\u0000\u0000\u0000\u0094\u0088\u0001\u0000\u0000\u0000\u0094\u0089\u0001"+ + "\u0000\u0000\u0000\u0094\u008a\u0001\u0000\u0000\u0000\u0094\u008b\u0001"+ + "\u0000\u0000\u0000\u0094\u008c\u0001\u0000\u0000\u0000\u0094\u008d\u0001"+ + "\u0000\u0000\u0000\u0094\u008e\u0001\u0000\u0000\u0000\u0094\u008f\u0001"+ + "\u0000\u0000\u0000\u0094\u0090\u0001\u0000\u0000\u0000\u0094\u0091\u0001"+ + "\u0000\u0000\u0000\u0094\u0092\u0001\u0000\u0000\u0000\u0094\u0093\u0001"+ + "\u0000\u0000\u0000\u0095\u0007\u0001\u0000\u0000\u0000\u0096\u0097\u0005"+ + "\u0014\u0000\u0000\u0097\u0098\u0003\n\u0005\u0000\u0098\t\u0001\u0000"+ + "\u0000\u0000\u0099\u009a\u0006\u0005\uffff\uffff\u0000\u009a\u009b\u0005"+ + "0\u0000\u0000\u009b\u00b6\u0003\n\u0005\u0007\u009c\u00b6\u0003\u000e"+ + "\u0007\u0000\u009d\u00b6\u0003\f\u0006\u0000\u009e\u00a0\u0003\u000e\u0007"+ + "\u0000\u009f\u00a1\u00050\u0000\u0000\u00a0\u009f\u0001\u0000\u0000\u0000"+ + "\u00a0\u00a1\u0001\u0000\u0000\u0000\u00a1\u00a2\u0001\u0000\u0000\u0000"+ + "\u00a2\u00a3\u0005-\u0000\u0000\u00a3\u00a4\u0005,\u0000\u0000\u00a4\u00a9"+ + "\u0003\u000e\u0007\u0000\u00a5\u00a6\u0005&\u0000\u0000\u00a6\u00a8\u0003"+ + "\u000e\u0007\u0000\u00a7\u00a5\u0001\u0000\u0000\u0000\u00a8\u00ab\u0001"+ + "\u0000\u0000\u0000\u00a9\u00a7\u0001\u0000\u0000\u0000\u00a9\u00aa\u0001"+ + "\u0000\u0000\u0000\u00aa\u00ac\u0001\u0000\u0000\u0000\u00ab\u00a9\u0001"+ + "\u0000\u0000\u0000\u00ac\u00ad\u00056\u0000\u0000\u00ad\u00b6\u0001\u0000"+ + "\u0000\u0000\u00ae\u00af\u0003\u000e\u0007\u0000\u00af\u00b1\u0005.\u0000"+ + "\u0000\u00b0\u00b2\u00050\u0000\u0000\u00b1\u00b0\u0001\u0000\u0000\u0000"+ + "\u00b1\u00b2\u0001\u0000\u0000\u0000\u00b2\u00b3\u0001\u0000\u0000\u0000"+ + "\u00b3\u00b4\u00051\u0000\u0000\u00b4\u00b6\u0001\u0000\u0000\u0000\u00b5"+ + "\u0099\u0001\u0000\u0000\u0000\u00b5\u009c\u0001\u0000\u0000\u0000\u00b5"+ + "\u009d\u0001\u0000\u0000\u0000\u00b5\u009e\u0001\u0000\u0000\u0000\u00b5"+ + "\u00ae\u0001\u0000\u0000\u0000\u00b6\u00bf\u0001\u0000\u0000\u0000\u00b7"+ + "\u00b8\n\u0004\u0000\u0000\u00b8\u00b9\u0005\"\u0000\u0000\u00b9\u00be"+ + "\u0003\n\u0005\u0005\u00ba\u00bb\n\u0003\u0000\u0000\u00bb\u00bc\u0005"+ + "3\u0000\u0000\u00bc\u00be\u0003\n\u0005\u0004\u00bd\u00b7\u0001\u0000"+ + "\u0000\u0000\u00bd\u00ba\u0001\u0000\u0000\u0000\u00be\u00c1\u0001\u0000"+ + "\u0000\u0000\u00bf\u00bd\u0001\u0000\u0000\u0000\u00bf\u00c0\u0001\u0000"+ + "\u0000\u0000\u00c0\u000b\u0001\u0000\u0000\u0000\u00c1\u00bf\u0001\u0000"+ + "\u0000\u0000\u00c2\u00c4\u0003\u000e\u0007\u0000\u00c3\u00c5\u00050\u0000"+ + "\u0000\u00c4\u00c3\u0001\u0000\u0000\u0000\u00c4\u00c5\u0001\u0000\u0000"+ + "\u0000\u00c5\u00c6\u0001\u0000\u0000\u0000\u00c6\u00c7\u0005/\u0000\u0000"+ + "\u00c7\u00c8\u0003^/\u0000\u00c8\u00d1\u0001\u0000\u0000\u0000\u00c9\u00cb"+ + "\u0003\u000e\u0007\u0000\u00ca\u00cc\u00050\u0000\u0000\u00cb\u00ca\u0001"+ + "\u0000\u0000\u0000\u00cb\u00cc\u0001\u0000\u0000\u0000\u00cc\u00cd\u0001"+ + "\u0000\u0000\u0000\u00cd\u00ce\u00055\u0000\u0000\u00ce\u00cf\u0003^/"+ + "\u0000\u00cf\u00d1\u0001\u0000\u0000\u0000\u00d0\u00c2\u0001\u0000\u0000"+ + "\u0000\u00d0\u00c9\u0001\u0000\u0000\u0000\u00d1\r\u0001\u0000\u0000\u0000"+ + "\u00d2\u00d8\u0003\u0010\b\u0000\u00d3\u00d4\u0003\u0010\b\u0000\u00d4"+ + "\u00d5\u0003`0\u0000\u00d5\u00d6\u0003\u0010\b\u0000\u00d6\u00d8\u0001"+ + "\u0000\u0000\u0000\u00d7\u00d2\u0001\u0000\u0000\u0000\u00d7\u00d3\u0001"+ + "\u0000\u0000\u0000\u00d8\u000f\u0001\u0000\u0000\u0000\u00d9\u00da\u0006"+ + "\b\uffff\uffff\u0000\u00da\u00de\u0003\u0012\t\u0000\u00db\u00dc\u0007"+ + "\u0000\u0000\u0000\u00dc\u00de\u0003\u0010\b\u0003\u00dd\u00d9\u0001\u0000"+ + "\u0000\u0000\u00dd\u00db\u0001\u0000\u0000\u0000\u00de\u00e7\u0001\u0000"+ + "\u0000\u0000\u00df\u00e0\n\u0002\u0000\u0000\u00e0\u00e1\u0007\u0001\u0000"+ + "\u0000\u00e1\u00e6\u0003\u0010\b\u0003\u00e2\u00e3\n\u0001\u0000\u0000"+ + "\u00e3\u00e4\u0007\u0000\u0000\u0000\u00e4\u00e6\u0003\u0010\b\u0002\u00e5"+ + "\u00df\u0001\u0000\u0000\u0000\u00e5\u00e2\u0001\u0000\u0000\u0000\u00e6"+ + "\u00e9\u0001\u0000\u0000\u0000\u00e7\u00e5\u0001\u0000\u0000\u0000\u00e7"+ + "\u00e8\u0001\u0000\u0000\u0000\u00e8\u0011\u0001\u0000\u0000\u0000\u00e9"+ + "\u00e7\u0001\u0000\u0000\u0000\u00ea\u00eb\u0006\t\uffff\uffff\u0000\u00eb"+ + "\u00f3\u0003:\u001d\u0000\u00ec\u00f3\u00030\u0018\u0000\u00ed\u00f3\u0003"+ + "\u0014\n\u0000\u00ee\u00ef\u0005,\u0000\u0000\u00ef\u00f0\u0003\n\u0005"+ + "\u0000\u00f0\u00f1\u00056\u0000\u0000\u00f1\u00f3\u0001\u0000\u0000\u0000"+ + "\u00f2\u00ea\u0001\u0000\u0000\u0000\u00f2\u00ec\u0001\u0000\u0000\u0000"+ + "\u00f2\u00ed\u0001\u0000\u0000\u0000\u00f2\u00ee\u0001\u0000\u0000\u0000"+ + "\u00f3\u00f9\u0001\u0000\u0000\u0000\u00f4\u00f5\n\u0001\u0000\u0000\u00f5"+ + "\u00f6\u0005%\u0000\u0000\u00f6\u00f8\u0003\u0016\u000b\u0000\u00f7\u00f4"+ + "\u0001\u0000\u0000\u0000\u00f8\u00fb\u0001\u0000\u0000\u0000\u00f9\u00f7"+ + "\u0001\u0000\u0000\u0000\u00f9\u00fa\u0001\u0000\u0000\u0000\u00fa\u0013"+ + "\u0001\u0000\u0000\u0000\u00fb\u00f9\u0001\u0000\u0000\u0000\u00fc\u00fd"+ + "\u00036\u001b\u0000\u00fd\u0107\u0005,\u0000\u0000\u00fe\u0108\u0005A"+ + "\u0000\u0000\u00ff\u0104\u0003\n\u0005\u0000\u0100\u0101\u0005&\u0000"+ + "\u0000\u0101\u0103\u0003\n\u0005\u0000\u0102\u0100\u0001\u0000\u0000\u0000"+ + "\u0103\u0106\u0001\u0000\u0000\u0000\u0104\u0102\u0001\u0000\u0000\u0000"+ + "\u0104\u0105\u0001\u0000\u0000\u0000\u0105\u0108\u0001\u0000\u0000\u0000"+ + "\u0106\u0104\u0001\u0000\u0000\u0000\u0107\u00fe\u0001\u0000\u0000\u0000"+ + "\u0107\u00ff\u0001\u0000\u0000\u0000\u0107\u0108\u0001\u0000\u0000\u0000"+ + "\u0108\u0109\u0001\u0000\u0000\u0000\u0109\u010a\u00056\u0000\u0000\u010a"+ + "\u0015\u0001\u0000\u0000\u0000\u010b\u010c\u00036\u001b\u0000\u010c\u0017"+ + "\u0001\u0000\u0000\u0000\u010d\u010e\u0005\u0010\u0000\u0000\u010e\u010f"+ + "\u0003\u001a\r\u0000\u010f\u0019\u0001\u0000\u0000\u0000\u0110\u0115\u0003"+ + "\u001c\u000e\u0000\u0111\u0112\u0005&\u0000\u0000\u0112\u0114\u0003\u001c"+ + "\u000e\u0000\u0113\u0111\u0001\u0000\u0000\u0000\u0114\u0117\u0001\u0000"+ + "\u0000\u0000\u0115\u0113\u0001\u0000\u0000\u0000\u0115\u0116\u0001\u0000"+ + "\u0000\u0000\u0116\u001b\u0001\u0000\u0000\u0000\u0117\u0115\u0001\u0000"+ + "\u0000\u0000\u0118\u011e\u0003\n\u0005\u0000\u0119\u011a\u00030\u0018"+ + "\u0000\u011a\u011b\u0005$\u0000\u0000\u011b\u011c\u0003\n\u0005\u0000"+ + "\u011c\u011e\u0001\u0000\u0000\u0000\u011d\u0118\u0001\u0000\u0000\u0000"+ + "\u011d\u0119\u0001\u0000\u0000\u0000\u011e\u001d\u0001\u0000\u0000\u0000"+ + "\u011f\u0120\u0005\u0006\u0000\u0000\u0120\u0125\u0003 \u0010\u0000\u0121"+ + "\u0122\u0005&\u0000\u0000\u0122\u0124\u0003 \u0010\u0000\u0123\u0121\u0001"+ + "\u0000\u0000\u0000\u0124\u0127\u0001\u0000\u0000\u0000\u0125\u0123\u0001"+ + "\u0000\u0000\u0000\u0125\u0126\u0001\u0000\u0000\u0000\u0126\u0129\u0001"+ + "\u0000\u0000\u0000\u0127\u0125\u0001\u0000\u0000\u0000\u0128\u012a\u0003"+ + "\"\u0011\u0000\u0129\u0128\u0001\u0000\u0000\u0000\u0129\u012a\u0001\u0000"+ + "\u0000\u0000\u012a\u001f\u0001\u0000\u0000\u0000\u012b\u012c\u0005\u0019"+ + "\u0000\u0000\u012c!\u0001\u0000\u0000\u0000\u012d\u0130\u0003$\u0012\u0000"+ + "\u012e\u0130\u0003&\u0013\u0000\u012f\u012d\u0001\u0000\u0000\u0000\u012f"+ + "\u012e\u0001\u0000\u0000\u0000\u0130#\u0001\u0000\u0000\u0000\u0131\u0132"+ + "\u0005L\u0000\u0000\u0132\u0137\u0003 \u0010\u0000\u0133\u0134\u0005&"+ + "\u0000\u0000\u0134\u0136\u0003 \u0010\u0000\u0135\u0133\u0001\u0000\u0000"+ + "\u0000\u0136\u0139\u0001\u0000\u0000\u0000\u0137\u0135\u0001\u0000\u0000"+ + "\u0000\u0137\u0138\u0001\u0000\u0000\u0000\u0138%\u0001\u0000\u0000\u0000"+ + "\u0139\u0137\u0001\u0000\u0000\u0000\u013a\u013b\u0005E\u0000\u0000\u013b"+ + "\u013c\u0003$\u0012\u0000\u013c\u013d\u0005F\u0000\u0000\u013d\'\u0001"+ + "\u0000\u0000\u0000\u013e\u013f\u0005\r\u0000\u0000\u013f\u0144\u0003 "+ + "\u0010\u0000\u0140\u0141\u0005&\u0000\u0000\u0141\u0143\u0003 \u0010\u0000"+ + "\u0142\u0140\u0001\u0000\u0000\u0000\u0143\u0146\u0001\u0000\u0000\u0000"+ + "\u0144\u0142\u0001\u0000\u0000\u0000\u0144\u0145\u0001\u0000\u0000\u0000"+ + "\u0145\u0148\u0001\u0000\u0000\u0000\u0146\u0144\u0001\u0000\u0000\u0000"+ + "\u0147\u0149\u0003\u001a\r\u0000\u0148\u0147\u0001\u0000\u0000\u0000\u0148"+ + "\u0149\u0001\u0000\u0000\u0000\u0149\u014c\u0001\u0000\u0000\u0000\u014a"+ + "\u014b\u0005!\u0000\u0000\u014b\u014d\u0003\u001a\r\u0000\u014c\u014a"+ + "\u0001\u0000\u0000\u0000\u014c\u014d\u0001\u0000\u0000\u0000\u014d)\u0001"+ + "\u0000\u0000\u0000\u014e\u014f\u0005\u0004\u0000\u0000\u014f\u0150\u0003"+ + "\u001a\r\u0000\u0150+\u0001\u0000\u0000\u0000\u0151\u0153\u0005\u0013"+ + "\u0000\u0000\u0152\u0154\u0003\u001a\r\u0000\u0153\u0152\u0001\u0000\u0000"+ + "\u0000\u0153\u0154\u0001\u0000\u0000\u0000\u0154\u0157\u0001\u0000\u0000"+ + "\u0000\u0155\u0156\u0005!\u0000\u0000\u0156\u0158\u0003\u001a\r\u0000"+ + "\u0157\u0155\u0001\u0000\u0000\u0000\u0157\u0158\u0001\u0000\u0000\u0000"+ + "\u0158-\u0001\u0000\u0000\u0000\u0159\u015a\u0005\b\u0000\u0000\u015a"+ + "\u015d\u0003\u001a\r\u0000\u015b\u015c\u0005!\u0000\u0000\u015c\u015e"+ + "\u0003\u001a\r\u0000\u015d\u015b\u0001\u0000\u0000\u0000\u015d\u015e\u0001"+ + "\u0000\u0000\u0000\u015e/\u0001\u0000\u0000\u0000\u015f\u0164\u00036\u001b"+ + "\u0000\u0160\u0161\u0005(\u0000\u0000\u0161\u0163\u00036\u001b\u0000\u0162"+ + "\u0160\u0001\u0000\u0000\u0000\u0163\u0166\u0001\u0000\u0000\u0000\u0164"+ + "\u0162\u0001\u0000\u0000\u0000\u0164\u0165\u0001\u0000\u0000\u0000\u0165"+ + "1\u0001\u0000\u0000\u0000\u0166\u0164\u0001\u0000\u0000\u0000\u0167\u016c"+ + "\u00038\u001c\u0000\u0168\u0169\u0005(\u0000\u0000\u0169\u016b\u00038"+ + "\u001c\u0000\u016a\u0168\u0001\u0000\u0000\u0000\u016b\u016e\u0001\u0000"+ + "\u0000\u0000\u016c\u016a\u0001\u0000\u0000\u0000\u016c\u016d\u0001\u0000"+ + "\u0000\u0000\u016d3\u0001\u0000\u0000\u0000\u016e\u016c\u0001\u0000\u0000"+ + "\u0000\u016f\u0174\u00032\u0019\u0000\u0170\u0171\u0005&\u0000\u0000\u0171"+ + "\u0173\u00032\u0019\u0000\u0172\u0170\u0001\u0000\u0000\u0000\u0173\u0176"+ + "\u0001\u0000\u0000\u0000\u0174\u0172\u0001\u0000\u0000\u0000\u0174\u0175"+ + "\u0001\u0000\u0000\u0000\u01755\u0001\u0000\u0000\u0000\u0176\u0174\u0001"+ + "\u0000\u0000\u0000\u0177\u0178\u0007\u0002\u0000\u0000\u01787\u0001\u0000"+ + "\u0000\u0000\u0179\u017a\u0005P\u0000\u0000\u017a9\u0001\u0000\u0000\u0000"+ + "\u017b\u01a6\u00051\u0000\u0000\u017c\u017d\u0003\\.\u0000\u017d\u017e"+ + "\u0005G\u0000\u0000\u017e\u01a6\u0001\u0000\u0000\u0000\u017f\u01a6\u0003"+ + "Z-\u0000\u0180\u01a6\u0003\\.\u0000\u0181\u01a6\u0003V+\u0000\u0182\u01a6"+ + "\u0003<\u001e\u0000\u0183\u01a6\u0003^/\u0000\u0184\u0185\u0005E\u0000"+ + "\u0000\u0185\u018a\u0003X,\u0000\u0186\u0187\u0005&\u0000\u0000\u0187"+ + "\u0189\u0003X,\u0000\u0188\u0186\u0001\u0000\u0000\u0000\u0189\u018c\u0001"+ + "\u0000\u0000\u0000\u018a\u0188\u0001\u0000\u0000\u0000\u018a\u018b\u0001"+ + "\u0000\u0000\u0000\u018b\u018d\u0001\u0000\u0000\u0000\u018c\u018a\u0001"+ + "\u0000\u0000\u0000\u018d\u018e\u0005F\u0000\u0000\u018e\u01a6\u0001\u0000"+ + "\u0000\u0000\u018f\u0190\u0005E\u0000\u0000\u0190\u0195\u0003V+\u0000"+ + "\u0191\u0192\u0005&\u0000\u0000\u0192\u0194\u0003V+\u0000\u0193\u0191"+ + "\u0001\u0000\u0000\u0000\u0194\u0197\u0001\u0000\u0000\u0000\u0195\u0193"+ + "\u0001\u0000\u0000\u0000\u0195\u0196\u0001\u0000\u0000\u0000\u0196\u0198"+ + "\u0001\u0000\u0000\u0000\u0197\u0195\u0001\u0000\u0000\u0000\u0198\u0199"+ + "\u0005F\u0000\u0000\u0199\u01a6\u0001\u0000\u0000\u0000\u019a\u019b\u0005"+ + "E\u0000\u0000\u019b\u01a0\u0003^/\u0000\u019c\u019d\u0005&\u0000\u0000"+ + "\u019d\u019f\u0003^/\u0000\u019e\u019c\u0001\u0000\u0000\u0000\u019f\u01a2"+ + "\u0001\u0000\u0000\u0000\u01a0\u019e\u0001\u0000\u0000\u0000\u01a0\u01a1"+ + "\u0001\u0000\u0000\u0000\u01a1\u01a3\u0001\u0000\u0000\u0000\u01a2\u01a0"+ + "\u0001\u0000\u0000\u0000\u01a3\u01a4\u0005F\u0000\u0000\u01a4\u01a6\u0001"+ + "\u0000\u0000\u0000\u01a5\u017b\u0001\u0000\u0000\u0000\u01a5\u017c\u0001"+ + "\u0000\u0000\u0000\u01a5\u017f\u0001\u0000\u0000\u0000\u01a5\u0180\u0001"+ + "\u0000\u0000\u0000\u01a5\u0181\u0001\u0000\u0000\u0000\u01a5\u0182\u0001"+ + "\u0000\u0000\u0000\u01a5\u0183\u0001\u0000\u0000\u0000\u01a5\u0184\u0001"+ + "\u0000\u0000\u0000\u01a5\u018f\u0001\u0000\u0000\u0000\u01a5\u019a\u0001"+ + "\u0000\u0000\u0000\u01a6;\u0001\u0000\u0000\u0000\u01a7\u01aa\u00054\u0000"+ + "\u0000\u01a8\u01aa\u0005D\u0000\u0000\u01a9\u01a7\u0001\u0000\u0000\u0000"+ + "\u01a9\u01a8\u0001\u0000\u0000\u0000\u01aa=\u0001\u0000\u0000\u0000\u01ab"+ + "\u01ac\u0005\n\u0000\u0000\u01ac\u01ad\u0005\u001f\u0000\u0000\u01ad?"+ + "\u0001\u0000\u0000\u0000\u01ae\u01af\u0005\u0012\u0000\u0000\u01af\u01b4"+ + "\u0003B!\u0000\u01b0\u01b1\u0005&\u0000\u0000\u01b1\u01b3\u0003B!\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"+ + "\u01b5A\u0001\u0000\u0000\u0000\u01b6\u01b4\u0001\u0000\u0000\u0000\u01b7"+ + "\u01b9\u0003\n\u0005\u0000\u01b8\u01ba\u0007\u0003\u0000\u0000\u01b9\u01b8"+ + "\u0001\u0000\u0000\u0000\u01b9\u01ba\u0001\u0000\u0000\u0000\u01ba\u01bd"+ + "\u0001\u0000\u0000\u0000\u01bb\u01bc\u00052\u0000\u0000\u01bc\u01be\u0007"+ + "\u0004\u0000\u0000\u01bd\u01bb\u0001\u0000\u0000\u0000\u01bd\u01be\u0001"+ + "\u0000\u0000\u0000\u01beC\u0001\u0000\u0000\u0000\u01bf\u01c0\u0005\t"+ + "\u0000\u0000\u01c0\u01c1\u00034\u001a\u0000\u01c1E\u0001\u0000\u0000\u0000"+ + "\u01c2\u01c3\u0005\u0002\u0000\u0000\u01c3\u01c4\u00034\u001a\u0000\u01c4"+ + "G\u0001\u0000\u0000\u0000\u01c5\u01c6\u0005\u000f\u0000\u0000\u01c6\u01cb"+ + "\u0003J%\u0000\u01c7\u01c8\u0005&\u0000\u0000\u01c8\u01ca\u0003J%\u0000"+ + "\u01c9\u01c7\u0001\u0000\u0000\u0000\u01ca\u01cd\u0001\u0000\u0000\u0000"+ + "\u01cb\u01c9\u0001\u0000\u0000\u0000\u01cb\u01cc\u0001\u0000\u0000\u0000"+ + "\u01ccI\u0001\u0000\u0000\u0000\u01cd\u01cb\u0001\u0000\u0000\u0000\u01ce"+ + "\u01cf\u00032\u0019\u0000\u01cf\u01d0\u0005T\u0000\u0000\u01d0\u01d1\u0003"+ + "2\u0019\u0000\u01d1K\u0001\u0000\u0000\u0000\u01d2\u01d3\u0005\u0001\u0000"+ + "\u0000\u01d3\u01d4\u0003\u0012\t\u0000\u01d4\u01d6\u0003^/\u0000\u01d5"+ + "\u01d7\u0003R)\u0000\u01d6\u01d5\u0001\u0000\u0000\u0000\u01d6\u01d7\u0001"+ + "\u0000\u0000\u0000\u01d7M\u0001\u0000\u0000\u0000\u01d8\u01d9\u0005\u0007"+ + "\u0000\u0000\u01d9\u01da\u0003\u0012\t\u0000\u01da\u01db\u0003^/\u0000"+ + "\u01dbO\u0001\u0000\u0000\u0000\u01dc\u01dd\u0005\u000e\u0000\u0000\u01dd"+ + "\u01de\u00030\u0018\u0000\u01deQ\u0001\u0000\u0000\u0000\u01df\u01e4\u0003"+ + "T*\u0000\u01e0\u01e1\u0005&\u0000\u0000\u01e1\u01e3\u0003T*\u0000\u01e2"+ + "\u01e0\u0001\u0000\u0000\u0000\u01e3\u01e6\u0001\u0000\u0000\u0000\u01e4"+ + "\u01e2\u0001\u0000\u0000\u0000\u01e4\u01e5\u0001\u0000\u0000\u0000\u01e5"+ + "S\u0001\u0000\u0000\u0000\u01e6\u01e4\u0001\u0000\u0000\u0000\u01e7\u01e8"+ + "\u00036\u001b\u0000\u01e8\u01e9\u0005$\u0000\u0000\u01e9\u01ea\u0003:"+ + "\u001d\u0000\u01eaU\u0001\u0000\u0000\u0000\u01eb\u01ec\u0007\u0005\u0000"+ + "\u0000\u01ecW\u0001\u0000\u0000\u0000\u01ed\u01f0\u0003Z-\u0000\u01ee"+ + "\u01f0\u0003\\.\u0000\u01ef\u01ed\u0001\u0000\u0000\u0000\u01ef\u01ee"+ + "\u0001\u0000\u0000\u0000\u01f0Y\u0001\u0000\u0000\u0000\u01f1\u01f3\u0007"+ + "\u0000\u0000\u0000\u01f2\u01f1\u0001\u0000\u0000\u0000\u01f2\u01f3\u0001"+ + "\u0000\u0000\u0000\u01f3\u01f4\u0001\u0000\u0000\u0000\u01f4\u01f5\u0005"+ + " \u0000\u0000\u01f5[\u0001\u0000\u0000\u0000\u01f6\u01f8\u0007\u0000\u0000"+ + "\u0000\u01f7\u01f6\u0001\u0000\u0000\u0000\u01f7\u01f8\u0001\u0000\u0000"+ + "\u0000\u01f8\u01f9\u0001\u0000\u0000\u0000\u01f9\u01fa\u0005\u001f\u0000"+ + "\u0000\u01fa]\u0001\u0000\u0000\u0000\u01fb\u01fc\u0005\u001e\u0000\u0000"+ + "\u01fc_\u0001\u0000\u0000\u0000\u01fd\u01fe\u0007\u0006\u0000\u0000\u01fe"+ + "a\u0001\u0000\u0000\u0000\u01ff\u0200\u0005\u0005\u0000\u0000\u0200\u0201"+ + "\u0003d2\u0000\u0201c\u0001\u0000\u0000\u0000\u0202\u0203\u0005E\u0000"+ + "\u0000\u0203\u0204\u0003\u0002\u0001\u0000\u0204\u0205\u0005F\u0000\u0000"+ + "\u0205e\u0001\u0000\u0000\u0000\u0206\u0207\u0005\u0011\u0000\u0000\u0207"+ + "\u0208\u0005j\u0000\u0000\u0208g\u0001\u0000\u0000\u0000\u0209\u020a\u0005"+ + "\f\u0000\u0000\u020a\u020b\u0005n\u0000\u0000\u020bi\u0001\u0000\u0000"+ + "\u0000\u020c\u020d\u0005\u0003\u0000\u0000\u020d\u0210\u0005Z\u0000\u0000"+ + "\u020e\u020f\u0005X\u0000\u0000\u020f\u0211\u00032\u0019\u0000\u0210\u020e"+ + "\u0001\u0000\u0000\u0000\u0210\u0211\u0001\u0000\u0000\u0000\u0211\u021b"+ + "\u0001\u0000\u0000\u0000\u0212\u0213\u0005Y\u0000\u0000\u0213\u0218\u0003"+ + "l6\u0000\u0214\u0215\u0005&\u0000\u0000\u0215\u0217\u0003l6\u0000\u0216"+ + "\u0214\u0001\u0000\u0000\u0000\u0217\u021a\u0001\u0000\u0000\u0000\u0218"+ + "\u0216\u0001\u0000\u0000\u0000\u0218\u0219\u0001\u0000\u0000\u0000\u0219"+ + "\u021c\u0001\u0000\u0000\u0000\u021a\u0218\u0001\u0000\u0000\u0000\u021b"+ + "\u0212\u0001\u0000\u0000\u0000\u021b\u021c\u0001\u0000\u0000\u0000\u021c"+ + "k\u0001\u0000\u0000\u0000\u021d\u021e\u00032\u0019\u0000\u021e\u021f\u0005"+ + "$\u0000\u0000\u021f\u0221\u0001\u0000\u0000\u0000\u0220\u021d\u0001\u0000"+ + "\u0000\u0000\u0220\u0221\u0001\u0000\u0000\u0000\u0221\u0222\u0001\u0000"+ + "\u0000\u0000\u0222\u0223\u00032\u0019\u0000\u0223m\u0001\u0000\u0000\u0000"+ + "\u0224\u0225\u0005\u000b\u0000\u0000\u0225\u0226\u0005\u0019\u0000\u0000"+ + "\u0226\u0227\u0005X\u0000\u0000\u0227\u0228\u00034\u001a\u0000\u0228o"+ + "\u0001\u0000\u0000\u00005{\u0084\u0094\u00a0\u00a9\u00b1\u00b5\u00bd\u00bf"+ + "\u00c4\u00cb\u00d0\u00d7\u00dd\u00e5\u00e7\u00f2\u00f9\u0104\u0107\u0115"+ + "\u011d\u0125\u0129\u012f\u0137\u0144\u0148\u014c\u0153\u0157\u015d\u0164"+ + "\u016c\u0174\u018a\u0195\u01a0\u01a5\u01a9\u01b4\u01b9\u01bd\u01cb\u01d6"+ + "\u01e4\u01ef\u01f2\u01f7\u0210\u0218\u021b\u0220"; 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 760e8f4cb9cd3..0da4c187a3d43 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 @@ -581,13 +581,13 @@ public class EsqlBaseParserBaseListener implements EsqlBaseParserListener { * *

The default implementation does nothing.

*/ - @Override public void enterInputParam(EsqlBaseParser.InputParamContext ctx) { } + @Override public void enterInputParams(EsqlBaseParser.InputParamsContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void exitInputParam(EsqlBaseParser.InputParamContext ctx) { } + @Override public void exitInputParams(EsqlBaseParser.InputParamsContext ctx) { } /** * {@inheritDoc} * @@ -636,6 +636,30 @@ public class EsqlBaseParserBaseListener implements EsqlBaseParserListener { *

The default implementation does nothing.

*/ @Override public void exitStringArrayLiteral(EsqlBaseParser.StringArrayLiteralContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInputParam(EsqlBaseParser.InputParamContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInputParam(EsqlBaseParser.InputParamContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext 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 aee998364f947..ea1c9aca99880 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 @@ -347,7 +347,7 @@ public class EsqlBaseParserBaseVisitor extends AbstractParseTreeVisitor im *

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

*/ - @Override public T visitInputParam(EsqlBaseParser.InputParamContext ctx) { return visitChildren(ctx); } + @Override public T visitInputParams(EsqlBaseParser.InputParamsContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * @@ -376,6 +376,20 @@ public class EsqlBaseParserBaseVisitor extends AbstractParseTreeVisitor im * {@link #visitChildren} on {@code ctx}.

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

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

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

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

+ */ + @Override public T visitInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext 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 0c53191ab9ab7..081deb03e8354 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 @@ -526,17 +526,17 @@ public interface EsqlBaseParserListener extends ParseTreeListener { */ void exitBooleanLiteral(EsqlBaseParser.BooleanLiteralContext ctx); /** - * Enter a parse tree produced by the {@code inputParam} + * Enter a parse tree produced by the {@code inputParams} * labeled alternative in {@link EsqlBaseParser#constant}. * @param ctx the parse tree */ - void enterInputParam(EsqlBaseParser.InputParamContext ctx); + void enterInputParams(EsqlBaseParser.InputParamsContext ctx); /** - * Exit a parse tree produced by the {@code inputParam} + * Exit a parse tree produced by the {@code inputParams} * labeled alternative in {@link EsqlBaseParser#constant}. * @param ctx the parse tree */ - void exitInputParam(EsqlBaseParser.InputParamContext ctx); + void exitInputParams(EsqlBaseParser.InputParamsContext ctx); /** * Enter a parse tree produced by the {@code stringLiteral} * labeled alternative in {@link EsqlBaseParser#constant}. @@ -585,6 +585,30 @@ public interface EsqlBaseParserListener extends ParseTreeListener { * @param ctx the parse tree */ void exitStringArrayLiteral(EsqlBaseParser.StringArrayLiteralContext ctx); + /** + * Enter a parse tree produced by the {@code inputParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + */ + void enterInputParam(EsqlBaseParser.InputParamContext ctx); + /** + * Exit a parse tree produced by the {@code inputParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + */ + void exitInputParam(EsqlBaseParser.InputParamContext ctx); + /** + * Enter a parse tree produced by the {@code inputNamedOrPositionalParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + */ + void enterInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext ctx); + /** + * Exit a parse tree produced by the {@code inputNamedOrPositionalParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + */ + void exitInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext ctx); /** * Enter a parse tree produced by {@link EsqlBaseParser#limitCommand}. * @param ctx the parse tree 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 54f506c9d3b3c..d1ffbd5fa0b32 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 @@ -317,12 +317,12 @@ public interface EsqlBaseParserVisitor extends ParseTreeVisitor { */ T visitBooleanLiteral(EsqlBaseParser.BooleanLiteralContext ctx); /** - * Visit a parse tree produced by the {@code inputParam} + * Visit a parse tree produced by the {@code inputParams} * labeled alternative in {@link EsqlBaseParser#constant}. * @param ctx the parse tree * @return the visitor result */ - T visitInputParam(EsqlBaseParser.InputParamContext ctx); + T visitInputParams(EsqlBaseParser.InputParamsContext ctx); /** * Visit a parse tree produced by the {@code stringLiteral} * labeled alternative in {@link EsqlBaseParser#constant}. @@ -351,6 +351,20 @@ public interface EsqlBaseParserVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitStringArrayLiteral(EsqlBaseParser.StringArrayLiteralContext ctx); + /** + * Visit a parse tree produced by the {@code inputParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInputParam(EsqlBaseParser.InputParamContext ctx); + /** + * Visit a parse tree produced by the {@code inputNamedOrPositionalParam} + * labeled alternative in {@link EsqlBaseParser#params}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext ctx); /** * Visit a parse tree produced by {@link EsqlBaseParser#limitCommand}. * @param ctx the parse tree 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 147d946dcef0f..56822386b2954 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 @@ -22,23 +22,23 @@ import org.elasticsearch.xpack.esql.core.parser.CaseChangingCharStream; import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan; -import java.util.HashMap; -import java.util.List; +import java.util.BitSet; import java.util.Map; import java.util.function.BiFunction; import java.util.function.Function; import static org.elasticsearch.xpack.esql.core.parser.ParserUtils.source; +import static org.elasticsearch.xpack.esql.core.util.StringUtils.isInteger; public class EsqlParser { private static final Logger log = LogManager.getLogger(EsqlParser.class); public LogicalPlan createStatement(String query) { - return createStatement(query, List.of()); + return createStatement(query, QueryParams.EMPTY); } - public LogicalPlan createStatement(String query, List params) { + public LogicalPlan createStatement(String query, QueryParams params) { if (log.isDebugEnabled()) { log.debug("Parsing as statement: {}", query); } @@ -47,7 +47,7 @@ public LogicalPlan createStatement(String query, List params) { private T invokeParser( String query, - List params, + QueryParams params, Function parseFunction, BiFunction result ) { @@ -57,8 +57,8 @@ private T invokeParser( lexer.removeErrorListeners(); lexer.addErrorListener(ERROR_LISTENER); - Map paramTokens = new HashMap<>(); - TokenSource tokenSource = new ParametrizedTokenSource(lexer, paramTokens, params); + Map positionalParamTokens = params.positionalParamTokens(); + TokenSource tokenSource = new ParametrizedTokenSource(lexer, positionalParamTokens, params); CommonTokenStream tokenStream = new CommonTokenStream(tokenSource); EsqlBaseParser parser = new EsqlBaseParser(tokenStream); @@ -76,7 +76,7 @@ private T invokeParser( log.trace("Parse tree: {}", tree.toStringTree()); } - return result.apply(new AstBuilder(paramTokens), tree); + return result.apply(new AstBuilder(params), tree); } catch (StackOverflowError e) { throw new ParsingException("ESQL statement is too large, causing stack overflow when generating the parsing tree: [{}]", query); } @@ -119,11 +119,14 @@ public void syntaxError( private static class ParametrizedTokenSource implements TokenSource { private TokenSource delegate; - private Map paramTokens; + private Map paramTokens; private int param; - private List params; + private QueryParams params; + private BitSet paramTypes = new BitSet(3); + private static String message = "Inconsistent parameter declaration, " + + "use one of positional, named or anonymous params but not a combination of "; - ParametrizedTokenSource(TokenSource delegate, Map paramTokens, List params) { + ParametrizedTokenSource(TokenSource delegate, Map paramTokens, QueryParams params) { this.delegate = delegate; this.paramTokens = paramTokens; this.params = params; @@ -134,12 +137,21 @@ private static class ParametrizedTokenSource implements TokenSource { public Token nextToken() { Token token = delegate.nextToken(); if (token.getType() == EsqlBaseLexer.PARAM) { - if (param >= params.size()) { - throw new ParsingException("Not enough actual parameters {}", params.size()); + checkAnonymousParam(token); + if (param >= params.positionalParams().size()) { + throw new ParsingException(source(token), "Not enough actual parameters {}", params.positionalParams().size()); } - paramTokens.put(token, params.get(param)); + paramTokens.put(token, params.positionalParams().get(param)); param++; } + + if (token.getType() == EsqlBaseLexer.NAMED_OR_POSITIONAL_PARAM) { + if (isInteger(token.getText().substring(1))) { + checkPositionalParam(token); + } else { + checkNamedParam(token); + } + } return token; } @@ -172,5 +184,26 @@ public void setTokenFactory(TokenFactory factory) { public TokenFactory getTokenFactory() { return delegate.getTokenFactory(); } + + private void checkAnonymousParam(Token token) { + paramTypes.set(0); + if (paramTypes.cardinality() > 1) { + throw new ParsingException(source(token), message + "anonymous and " + (paramTypes.get(1) ? "named" : "positional")); + } + } + + private void checkNamedParam(Token token) { + paramTypes.set(1); + if (paramTypes.cardinality() > 1) { + throw new ParsingException(source(token), message + "named and " + (paramTypes.get(0) ? "anonymous" : "positional")); + } + } + + private void checkPositionalParam(Token token) { + paramTypes.set(2); + if (paramTypes.cardinality() > 1) { + throw new ParsingException(source(token), message + "positional and " + (paramTypes.get(0) ? "anonymous" : "named")); + } + } } } 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 a32ae9167aeb2..59801e59555b5 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 @@ -18,7 +18,6 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; -import org.elasticsearch.xpack.esql.core.QlIllegalArgumentException; import org.elasticsearch.xpack.esql.core.expression.Alias; import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -68,7 +67,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -82,6 +80,7 @@ import static org.elasticsearch.xpack.esql.core.util.NumericUtils.asLongUnsigned; import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber; import static org.elasticsearch.xpack.esql.core.util.StringUtils.WILDCARD; +import static org.elasticsearch.xpack.esql.core.util.StringUtils.isInteger; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.bigIntegerToUnsignedLong; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.parseTemporalAmout; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToIntegral; @@ -95,9 +94,9 @@ public abstract class ExpressionBuilder extends IdentifierBuilder { */ public static final int MAX_EXPRESSION_DEPTH = 500; - private final Map params; + protected final QueryParams params; - ExpressionBuilder(Map params) { + ExpressionBuilder(QueryParams params) { this.params = params; } @@ -691,62 +690,64 @@ public List visitGrouping(EsqlBaseParser.FieldsContext ctx) { @Override public Object visitInputParam(EsqlBaseParser.InputParamContext ctx) { - TypedParamValue param = param(ctx.PARAM()); - DataType dataType = EsqlDataTypes.fromTypeName(param.type); - Source source = source(ctx); - if (dataType == null) { - throw new ParsingException(source, "Invalid parameter data type [{}]", param.type); - } - if (param.value == null) { - // no conversion is required for null values - return new Literal(source, null, dataType); - } - final DataType sourceType; - try { - sourceType = DataType.fromJava(param.value); - } catch (QlIllegalArgumentException ex) { - throw new ParsingException( - ex, - source, - "Unexpected actual parameter type [{}] for type [{}]", - param.value.getClass().getName(), - param.type - ); - } - if (sourceType == dataType) { - // no conversion is required if the value is already have correct type - return new Literal(source, param.value, dataType); - } - // otherwise we need to make sure that xcontent-serialized value is converted to the correct type - try { + QueryParam param = paramByToken(ctx.PARAM()); + return visitParam(ctx, param); + } - if (EsqlDataTypeConverter.canConvert(sourceType, dataType) == false) { - throw new ParsingException( - source, - "Cannot cast value [{}] of type [{}] to parameter type [{}]", - param.value, - sourceType, - dataType - ); - } - return new Literal(source, EsqlDataTypeConverter.converterFor(sourceType, dataType).convert(param.value), dataType); - } catch (QlIllegalArgumentException ex) { - throw new ParsingException(ex, source, "Unexpected actual parameter type [{}] for type [{}]", sourceType, param.type); + @Override + public Object visitInputNamedOrPositionalParam(EsqlBaseParser.InputNamedOrPositionalParamContext ctx) { + QueryParam param = paramByNameOrPosition(ctx.NAMED_OR_POSITIONAL_PARAM()); + if (param == null) { + return Literal.NULL; } + return visitParam(ctx, param); + } + + private Object visitParam(EsqlBaseParser.ParamsContext ctx, QueryParam param) { + Source source = source(ctx); + DataType type = param.type(); + return new Literal(source, param.value(), type); } - private TypedParamValue param(TerminalNode node) { + QueryParam paramByToken(TerminalNode node) { if (node == null) { return null; } - Token token = node.getSymbol(); - - if (params.containsKey(token) == false) { + if (params.contains(token) == false) { throw new ParsingException(source(node), "Unexpected parameter"); } - return params.get(token); } + QueryParam paramByNameOrPosition(TerminalNode node) { + if (node == null) { + return null; + } + Token token = node.getSymbol(); + String nameOrPosition = token.getText().substring(1); + if (isInteger(nameOrPosition)) { + int index = Integer.parseInt(nameOrPosition); + if (params.get(index) == null) { + String message = ""; + int np = params.positionalParams().size(); + if (np > 0) { + message = ", did you mean " + (np == 1 ? "position 1?" : "any position between 1 and " + np + "?"); + } + params.addParsingError(new ParsingException(source(node), "No parameter is defined for position " + index + message)); + } + return params.get(index); + } else { + if (params.contains(nameOrPosition) == false) { + String message = ""; + List potentialMatches = StringUtils.findSimilar(nameOrPosition, params.namedParams().keySet()); + if (potentialMatches.size() > 0) { + message = ", did you mean " + + (potentialMatches.size() == 1 ? "[" + potentialMatches.get(0) + "]?" : "any of " + potentialMatches + "?"); + } + params.addParsingError(new ParsingException(source(node), "Unknown query parameter [" + nameOrPosition + "]" + message)); + } + return params.get(nameOrPosition); + } + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java index ec238c1fcf316..f829a7cb6ed00 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java @@ -85,12 +85,25 @@ public class LogicalPlanBuilder extends ExpressionBuilder { */ public static final int MAX_QUERY_DEPTH = 500; - public LogicalPlanBuilder(Map params) { + public LogicalPlanBuilder(QueryParams params) { super(params); } protected LogicalPlan plan(ParseTree ctx) { - return ParserUtils.typedParsing(this, ctx, LogicalPlan.class); + LogicalPlan p = ParserUtils.typedParsing(this, ctx, LogicalPlan.class); + var errors = this.params.parsingErrors(); + if (errors.isEmpty()) { + return p; + } else { + StringBuilder message = new StringBuilder(); + for (int i = 0; i < errors.size(); i++) { + if (i > 0) { + message.append("; "); + } + message.append(errors.get(i).getMessage()); + } + throw new ParsingException(message.toString()); + } } protected List plans(List ctxs) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParam.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParam.java new file mode 100644 index 0000000000000..022c18fdc586c --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParam.java @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.esql.parser; + +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * Represent a strongly typed parameter value + */ +public record QueryParam(String name, Object value, DataType type) { + + public String nameValue() { + return "{" + (this.name == null ? "" : this.name + ":") + this.value + "}"; + } + + @Override + public String toString() { + return value + " [" + name + "][" + type + "]"; + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParams.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParams.java new file mode 100644 index 0000000000000..ebba6d3d0b482 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/QueryParams.java @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.parser; + +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class QueryParams { + + public static final QueryParams EMPTY = new QueryParams(); + + // This matches the named or unnamed parameters specified in an EsqlQueryRequest.params. + private List params = new ArrayList<>(); + + // This matches the named parameters specified in an EsqlQueryRequest.params. + private Map nameToParam = new HashMap<>(); + + // This is populated by EsqlParser, each parameter marker has an entry. + private Map tokenToParam = new HashMap<>(); + + private List parsingErrors = new ArrayList<>(); + + public QueryParams() {} + + public QueryParams(List params) { + for (QueryParam p : params) { + this.params.add(p); + String name = p.name(); + if (name != null) { + nameToParam.put(name, p); + } + } + } + + public List positionalParams() { + return this.params; + } + + public QueryParam get(int index) { + return (index <= 0 || index > params.size()) ? null : params.get(index - 1); + } + + public Map namedParams() { + return this.nameToParam; + } + + public boolean contains(String paramName) { + return this.nameToParam.containsKey(paramName); + } + + public QueryParam get(String paramName) { + return nameToParam.get(paramName); + } + + public Map positionalParamTokens() { + return this.tokenToParam; + } + + public boolean contains(Token token) { + return this.tokenToParam.containsKey(token); + } + + public QueryParam get(Token tokenLocation) { + return this.tokenToParam.get(tokenLocation); + } + + public List parsingErrors() { + return this.parsingErrors; + } + + public void addParsingError(ParsingException e) { + this.parsingErrors.add(e); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/TypedParamValue.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/TypedParamValue.java deleted file mode 100644 index 74cc53e51b360..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/TypedParamValue.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package org.elasticsearch.xpack.esql.parser; - -import java.util.Objects; - -/** - * Represent a strongly typed parameter value - */ -public class TypedParamValue { - - public final Object value; - public final String type; - private boolean hasExplicitType; // the type is explicitly set in the request or inferred by the parser - private ContentLocation tokenLocation; // location of the token failing the parsing rules - - public TypedParamValue(String type, Object value) { - this(type, value, true); - } - - public TypedParamValue(String type, Object value, boolean hasExplicitType) { - this.value = value; - this.type = type; - this.hasExplicitType = hasExplicitType; - } - - public boolean hasExplicitType() { - return hasExplicitType; - } - - public void hasExplicitType(boolean hasExplicitType) { - this.hasExplicitType = hasExplicitType; - } - - public ContentLocation tokenLocation() { - return tokenLocation; - } - - public void tokenLocation(ContentLocation tokenLocation) { - this.tokenLocation = tokenLocation; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TypedParamValue that = (TypedParamValue) o; - return Objects.equals(value, that.value) - && Objects.equals(type, that.type) - && Objects.equals(hasExplicitType, that.hasExplicitType); - } - - @Override - public int hashCode() { - return Objects.hash(value, type, hasExplicitType); - } - - @Override - public String toString() { - return String.valueOf(value) + " [" + type + "][" + hasExplicitType + "][" + tokenLocation + "]"; - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java index 10116bb24e6b9..1f5374b73466e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java @@ -46,7 +46,7 @@ import org.elasticsearch.xpack.esql.optimizer.PhysicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.PhysicalPlanOptimizer; import org.elasticsearch.xpack.esql.parser.EsqlParser; -import org.elasticsearch.xpack.esql.parser.TypedParamValue; +import org.elasticsearch.xpack.esql.parser.QueryParams; import org.elasticsearch.xpack.esql.plan.logical.Aggregate; import org.elasticsearch.xpack.esql.plan.logical.Enrich; import org.elasticsearch.xpack.esql.plan.logical.Keep; @@ -139,7 +139,7 @@ public void execute(EsqlQueryRequest request, ActionListener liste ); } - private LogicalPlan parse(String query, List params) { + private LogicalPlan parse(String query, QueryParams params) { var parsed = new EsqlParser().createStatement(query, params); LOGGER.debug("Parsed logical plan:\n{}", parsed); return parsed; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java index ab0bc114a2765..a8ad53b8bc663 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java @@ -29,12 +29,13 @@ import org.elasticsearch.tasks.TaskInfo; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xcontent.NamedXContentRegistry; +import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.XContentParserConfiguration; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xpack.esql.Column; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.parser.TypedParamValue; +import org.elasticsearch.xpack.esql.parser.QueryParam; import java.io.IOException; import java.util.ArrayList; @@ -57,7 +58,7 @@ public void testParseFields() throws IOException { Locale locale = randomLocale(random()); QueryBuilder filter = randomQueryBuilder(); - List params = randomParameters(); + List params = randomParameters(); boolean hasParams = params.isEmpty() == false; StringBuilder paramsString = paramsString(params, hasParams); String json = String.format(Locale.ROOT, """ @@ -75,20 +76,119 @@ public void testParseFields() throws IOException { assertEquals(locale.toLanguageTag(), request.locale().toLanguageTag()); assertEquals(locale, request.locale()); assertEquals(filter, request.filter()); - - assertEquals(params.size(), request.params().size()); + assertEquals(params.size(), request.params().positionalParams().size()); for (int i = 0; i < params.size(); i++) { - assertEquals(params.get(i), request.params().get(i)); + assertEquals(params.get(i), request.params().positionalParams().get(i)); + } + } + + public void testNamedParams() throws IOException { + String query = randomAlphaOfLengthBetween(1, 100); + boolean columnar = randomBoolean(); + Locale locale = randomLocale(random()); + QueryBuilder filter = randomQueryBuilder(); + + String paramsString = """ + ,"params":[ {"n1" : "8.15.0" }, { "n2" : 0.05 }, {"n3" : -799810013 }, + {"n4" : "127.0.0.1"}, {"n5" : "esql"}, {"n_6" : null}, {"n7_" : false}] }"""; + List params = new ArrayList<>(4); + params.add(new QueryParam("n1", "8.15.0", DataType.KEYWORD)); + params.add(new QueryParam("n2", 0.05, DataType.DOUBLE)); + params.add(new QueryParam("n3", -799810013, DataType.INTEGER)); + params.add(new QueryParam("n4", "127.0.0.1", DataType.KEYWORD)); + params.add(new QueryParam("n5", "esql", DataType.KEYWORD)); + params.add(new QueryParam("n_6", null, DataType.NULL)); + params.add(new QueryParam("n7_", false, DataType.BOOLEAN)); + String json = String.format(Locale.ROOT, """ + { + "query": "%s", + "columnar": %s, + "locale": "%s", + "filter": %s + %s""", query, columnar, locale.toLanguageTag(), filter, paramsString); + + EsqlQueryRequest request = parseEsqlQueryRequestSync(json); + + assertEquals(query, request.query()); + assertEquals(columnar, request.columnar()); + assertEquals(locale.toLanguageTag(), request.locale().toLanguageTag()); + assertEquals(locale, request.locale()); + assertEquals(filter, request.filter()); + assertEquals(params.size(), request.params().positionalParams().size()); + + for (int i = 0; i < request.params().positionalParams().size(); i++) { + assertEquals(params.get(i), request.params().positionalParams().get(i)); } } + public void testInvalidParams() throws IOException { + String query = randomAlphaOfLengthBetween(1, 100); + boolean columnar = randomBoolean(); + Locale locale = randomLocale(random()); + QueryBuilder filter = randomQueryBuilder(); + + String paramsString1 = """ + "params":[ {"1" : "v1" }, {"1x" : "v1" }, {"_a" : "v1" }, {"@-#" : "v1" }, 1, 2]"""; + String json1 = String.format(Locale.ROOT, """ + { + %s + "query": "%s", + "columnar": %s, + "locale": "%s", + "filter": %s + }""", paramsString1, query, columnar, locale.toLanguageTag(), filter); + + Exception e1 = expectThrows(XContentParseException.class, () -> parseEsqlQueryRequestSync(json1)); + assertThat( + e1.getCause().getMessage(), + containsString( + "Failed to parse params: [2:16] [1] is not a valid parameter name, " + + "a valid parameter name starts with a letter and contains letters, digits and underscores only" + ) + ); + assertThat(e1.getCause().getMessage(), containsString("[2:31] [1x] is not a valid parameter name")); + assertThat(e1.getCause().getMessage(), containsString("[2:47] [_a] is not a valid parameter name")); + assertThat(e1.getCause().getMessage(), containsString("[2:63] [@-#] is not a valid parameter name")); + assertThat( + e1.getCause().getMessage(), + containsString( + "Params cannot contain both named and unnamed parameters; got [{1:v1}, {1x:v1}, {_a:v1}, {@-#:v1}] and [{1}, {2}]" + ) + ); + + String paramsString2 = """ + "params":[ 1, 2, {"1" : "v1" }, {"1x" : "v1" }]"""; + String json2 = String.format(Locale.ROOT, """ + { + %s + "query": "%s", + "columnar": %s, + "locale": "%s", + "filter": %s + }""", paramsString2, query, columnar, locale.toLanguageTag(), filter); + + Exception e2 = expectThrows(XContentParseException.class, () -> parseEsqlQueryRequestSync(json2)); + assertThat( + e2.getCause().getMessage(), + containsString( + "Failed to parse params: [2:22] [1] is not a valid parameter name, " + + "a valid parameter name starts with a letter and contains letters, digits and underscores only" + ) + ); + assertThat(e2.getCause().getMessage(), containsString("[2:37] [1x] is not a valid parameter name")); + assertThat( + e2.getCause().getMessage(), + containsString("Params cannot contain both named and unnamed parameters; got [{1:v1}, {1x:v1}] and [{1}, {2}]") + ); + } + public void testParseFieldsForAsync() throws IOException { String query = randomAlphaOfLengthBetween(1, 100); boolean columnar = randomBoolean(); Locale locale = randomLocale(random()); QueryBuilder filter = randomQueryBuilder(); - List params = randomParameters(); + List params = randomParameters(); boolean hasParams = params.isEmpty() == false; StringBuilder paramsString = paramsString(params, hasParams); boolean keepOnCompletion = randomBoolean(); @@ -126,10 +226,9 @@ public void testParseFieldsForAsync() throws IOException { assertEquals(keepOnCompletion, request.keepOnCompletion()); assertEquals(waitForCompletion, request.waitForCompletionTimeout()); assertEquals(keepAlive, request.keepAlive()); - - assertEquals(params.size(), request.params().size()); + assertEquals(params.size(), request.params().positionalParams().size()); for (int i = 0; i < params.size(); i++) { - assertEquals(params.get(i), request.params().get(i)); + assertEquals(params.get(i), request.params().positionalParams().get(i)); } } @@ -378,22 +477,21 @@ public void testTask() throws IOException { assertThat(json, equalTo(expected)); } - private List randomParameters() { + private List randomParameters() { if (randomBoolean()) { return Collections.emptyList(); } else { int len = randomIntBetween(1, 10); - List arr = new ArrayList<>(len); + List arr = new ArrayList<>(len); for (int i = 0; i < len; i++) { - boolean hasExplicitType = randomBoolean(); @SuppressWarnings("unchecked") - Supplier supplier = randomFrom( - () -> new TypedParamValue("boolean", randomBoolean(), hasExplicitType), - () -> new TypedParamValue("integer", randomInt(), hasExplicitType), - () -> new TypedParamValue("long", randomLong(), hasExplicitType), - () -> new TypedParamValue("double", randomDouble(), hasExplicitType), - () -> new TypedParamValue("null", null, hasExplicitType), - () -> new TypedParamValue("keyword", randomAlphaOfLength(10), hasExplicitType) + Supplier supplier = randomFrom( + () -> new QueryParam(null, randomBoolean(), DataType.BOOLEAN), + () -> new QueryParam(null, randomInt(), DataType.INTEGER), + () -> new QueryParam(null, randomLong(), DataType.LONG), + () -> new QueryParam(null, randomDouble(), DataType.DOUBLE), + () -> new QueryParam(null, null, DataType.NULL), + () -> new QueryParam(null, randomAlphaOfLength(10), DataType.KEYWORD) ); arr.add(supplier.get()); } @@ -401,33 +499,22 @@ private List randomParameters() { } } - private StringBuilder paramsString(List params, boolean hasParams) { + private StringBuilder paramsString(List params, boolean hasParams) { StringBuilder paramsString = new StringBuilder(); if (hasParams) { paramsString.append(",\"params\":["); boolean first = true; - for (TypedParamValue param : params) { + for (QueryParam param : params) { if (first == false) { paramsString.append(", "); } first = false; - if (param.hasExplicitType()) { - paramsString.append("{\"type\":\""); - paramsString.append(param.type); - paramsString.append("\",\"value\":"); - } - switch (param.type) { - case "keyword" -> { - paramsString.append("\""); - paramsString.append(param.value); - paramsString.append("\""); - } - case "integer", "long", "boolean", "null", "double" -> { - paramsString.append(param.value); - } - } - if (param.hasExplicitType()) { - paramsString.append("}"); + if (param.type() == DataType.KEYWORD) { + paramsString.append("\""); + paramsString.append(param.value()); + paramsString.append("\""); + } else if (param.type().isNumeric() || param.type() == DataType.BOOLEAN || param.type() == DataType.NULL) { + paramsString.append(param.value()); } } paramsString.append("]}"); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 07a364bf9196e..e5f59f1ffa8ad 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -11,7 +11,8 @@ import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.parser.EsqlParser; -import org.elasticsearch.xpack.esql.parser.TypedParamValue; +import org.elasticsearch.xpack.esql.parser.QueryParam; +import org.elasticsearch.xpack.esql.parser.QueryParams; import org.elasticsearch.xpack.esql.type.EsqlDataTypes; import java.util.ArrayList; @@ -19,6 +20,8 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.loadMapping; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.NULL; import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -554,21 +557,21 @@ private String error(String query, Object... params) { } private String error(String query, Analyzer analyzer, Object... params) { - List parameters = new ArrayList<>(); + List parameters = new ArrayList<>(); for (Object param : params) { if (param == null) { - parameters.add(new TypedParamValue("null", null)); + parameters.add(new QueryParam(null, null, NULL)); } else if (param instanceof String) { - parameters.add(new TypedParamValue("keyword", param)); + parameters.add(new QueryParam(null, param, KEYWORD)); } else if (param instanceof Number) { - parameters.add(new TypedParamValue("param", param)); + parameters.add(new QueryParam(null, param, EsqlDataTypes.fromJava(param))); } else { throw new IllegalArgumentException("VerifierTests don't support params of type " + param.getClass()); } } VerificationException e = expectThrows( VerificationException.class, - () -> analyzer.analyze(parser.createStatement(query, parameters)) + () -> analyzer.analyze(parser.createStatement(query, new QueryParams(parameters))) ); String message = e.getMessage(); assertTrue(message.startsWith("Found ")); 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 884b24fc0fc57..28662c2470f15 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 @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.esql.parser; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.Build; import org.elasticsearch.core.Tuple; import org.elasticsearch.index.IndexMode; @@ -31,7 +30,6 @@ import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.core.plan.logical.OrderBy; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.core.util.StringUtils; import org.elasticsearch.xpack.esql.expression.function.scalar.string.RLike; import org.elasticsearch.xpack.esql.expression.function.scalar.string.WildcardLike; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add; @@ -52,11 +50,8 @@ import org.elasticsearch.xpack.esql.plan.logical.MvExpand; import org.elasticsearch.xpack.esql.plan.logical.Project; import org.elasticsearch.xpack.esql.plan.logical.Row; -import org.elasticsearch.xpack.versionfield.Version; import java.math.BigInteger; -import java.time.Duration; -import java.time.Period; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -68,6 +63,7 @@ import static org.elasticsearch.xpack.esql.core.expression.Literal.TRUE; import static org.elasticsearch.xpack.esql.core.expression.function.FunctionResolutionStrategy.DEFAULT; import static org.elasticsearch.xpack.esql.core.tree.Source.EMPTY; +import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.util.NumericUtils.asLongUnsigned; import static org.elasticsearch.xpack.esql.parser.ExpressionBuilder.breakIntoFragments; @@ -79,6 +75,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") public class StatementParserTests extends ESTestCase { private static String FROM = "from test"; @@ -409,7 +406,7 @@ public void testBasicLimitCommand() { } public void testLimitConstraints() { - expectError("from text | limit -1", "extraneous input '-' expecting INTEGER_LITERAL"); + expectError("from text | limit -1", "line 1:19: extraneous input '-' expecting INTEGER_LITERAL"); } public void testBasicSortCommand() { @@ -770,19 +767,23 @@ public void testUsageOfProject() { public void testInputParams() { LogicalPlan stm = statement( - "row x = ?, y = ?, a = ?, b = ?, c = ?, d = ?", - List.of( - new TypedParamValue("integer", 1), - new TypedParamValue("keyword", "2"), - new TypedParamValue("date_period", "2 days"), - new TypedParamValue("time_duration", "4 hours"), - new TypedParamValue("version", "1.2.3"), - new TypedParamValue("ip", "127.0.0.1") + "row x = ?, y = ?, a = ?, b = ?, c = ?, d = ?, e = ?-1, f = ?+1", + new QueryParams( + List.of( + new QueryParam(null, 1, INTEGER), + new QueryParam(null, "2", KEYWORD), + new QueryParam(null, "2 days", KEYWORD), + new QueryParam(null, "4 hours", KEYWORD), + new QueryParam(null, "1.2.3", KEYWORD), + new QueryParam(null, "127.0.0.1", KEYWORD), + new QueryParam(null, 10, INTEGER), + new QueryParam(null, 10, INTEGER) + ) ) ); assertThat(stm, instanceOf(Row.class)); Row row = (Row) stm; - assertThat(row.fields().size(), is(6)); + assertThat(row.fields().size(), is(8)); NamedExpression field = row.fields().get(0); assertThat(field.name(), is("x")); @@ -800,65 +801,346 @@ public void testInputParams() { assertThat(field.name(), is("a")); assertThat(field, instanceOf(Alias.class)); alias = (Alias) field; - assertThat(alias.child().fold(), is(Period.ofDays(2))); + assertThat(alias.child().fold(), is("2 days")); field = row.fields().get(3); assertThat(field.name(), is("b")); assertThat(field, instanceOf(Alias.class)); alias = (Alias) field; - assertThat(alias.child().fold(), is(Duration.ofHours(4))); + assertThat(alias.child().fold(), is("4 hours")); field = row.fields().get(4); assertThat(field.name(), is("c")); assertThat(field, instanceOf(Alias.class)); alias = (Alias) field; - assertThat(alias.child().fold().getClass(), is(BytesRef.class)); - assertThat(alias.child().fold().toString(), is(new Version("1.2.3").toBytesRef().toString())); + assertThat(alias.child().fold().getClass(), is(String.class)); + assertThat(alias.child().fold().toString(), is("1.2.3")); field = row.fields().get(5); assertThat(field.name(), is("d")); assertThat(field, instanceOf(Alias.class)); alias = (Alias) field; - assertThat(alias.child().fold().getClass(), is(BytesRef.class)); - assertThat(alias.child().fold().toString(), is(StringUtils.parseIP("127.0.0.1").toString())); + assertThat(alias.child().fold().getClass(), is(String.class)); + assertThat(alias.child().fold().toString(), is("127.0.0.1")); + + field = row.fields().get(6); + assertThat(field.name(), is("e")); + assertThat(field, instanceOf(Alias.class)); + alias = (Alias) field; + assertThat(alias.child().fold(), is(9)); + + field = row.fields().get(7); + assertThat(field.name(), is("f")); + assertThat(field, instanceOf(Alias.class)); + alias = (Alias) field; + assertThat(alias.child().fold(), is(11)); + } + + public void testMissingInputParams() { + expectError("row x = ?, y = ?", List.of(new QueryParam(null, 1, INTEGER)), "Not enough actual parameters 1"); + } + + public void testNamedParams() { + LogicalPlan stm = statement("row x=?name1, y = ?name1", new QueryParams(List.of(new QueryParam("name1", 1, INTEGER)))); + assertThat(stm, instanceOf(Row.class)); + Row row = (Row) stm; + assertThat(row.fields().size(), is(2)); + + NamedExpression field = row.fields().get(0); + assertThat(field.name(), is("x")); + assertThat(field, instanceOf(Alias.class)); + Alias alias = (Alias) field; + assertThat(alias.child().fold(), is(1)); + + field = row.fields().get(1); + assertThat(field.name(), is("y")); + assertThat(field, instanceOf(Alias.class)); + alias = (Alias) field; + assertThat(alias.child().fold(), is(1)); + } + + public void testInvalidNamedParams() { + expectError( + "from test | where x < ?n1 | eval y = ?n2", + List.of(new QueryParam("n1", 5, INTEGER)), + "Unknown query parameter [n2], did you mean [n1]?" + ); + + expectError( + "from test | where x < ?n1 | eval y = ?n2", + List.of(new QueryParam("n1", 5, INTEGER), new QueryParam("n3", 5, INTEGER)), + "Unknown query parameter [n2], did you mean any of [n1, n3]?" + ); + + expectError("from test | where x < ?_1", List.of(new QueryParam("_1", 5, INTEGER)), "extraneous input '_1' expecting "); + + expectError("from test | where x < ?#1", List.of(new QueryParam("#1", 5, INTEGER)), "token recognition error at: '#'"); + + expectError( + "from test | where x < ??", + List.of(new QueryParam("n_1", 5, INTEGER), new QueryParam("n_2", 5, INTEGER)), + "extraneous input '?' expecting " + ); + } + + public void testPositionalParams() { + LogicalPlan stm = statement("row x=?1, y=?1", new QueryParams(List.of(new QueryParam(null, 1, INTEGER)))); + assertThat(stm, instanceOf(Row.class)); + Row row = (Row) stm; + assertThat(row.fields().size(), is(2)); + + NamedExpression field = row.fields().get(0); + assertThat(field.name(), is("x")); + assertThat(field, instanceOf(Alias.class)); + Alias alias = (Alias) field; + assertThat(alias.child().fold(), is(1)); + + field = row.fields().get(1); + assertThat(field.name(), is("y")); + assertThat(field, instanceOf(Alias.class)); + alias = (Alias) field; + assertThat(alias.child().fold(), is(1)); } - public void testWrongIntervalParams() { - expectError("row x = ?", List.of(new TypedParamValue("date_period", "12")), "Cannot parse [12] to DATE_PERIOD"); - expectError("row x = ?", List.of(new TypedParamValue("time_duration", "12")), "Cannot parse [12] to TIME_DURATION"); + public void testInvalidPositionalParams() { expectError( - "row x = ?", - List.of(new TypedParamValue("date_period", "12 months foo")), - "Cannot parse [12 months foo] to DATE_PERIOD" + "from test | where x < ?0", + List.of(new QueryParam(null, 5, INTEGER)), + "No parameter is defined for position 0, did you mean position 1" ); + expectError( - "row x = ?", - List.of(new TypedParamValue("time_duration", "12 minutes bar")), - "Cannot parse [12 minutes bar] to TIME_DURATION" + "from test | where x < ?2", + List.of(new QueryParam(null, 5, INTEGER)), + "No parameter is defined for position 2, did you mean position 1" ); - expectError("row x = ?", List.of(new TypedParamValue("date_period", "12 foo")), "Unexpected time interval qualifier: 'foo'"); - expectError("row x = ?", List.of(new TypedParamValue("time_duration", "12 bar")), "Unexpected time interval qualifier: 'bar'"); - expectError("row x = ?", List.of(new TypedParamValue("date_period", "foo days")), "Cannot parse [foo days] to DATE_PERIOD"); + expectError( - "row x = ?", - List.of(new TypedParamValue("time_duration", "bar seconds")), - "Cannot parse [bar seconds] to TIME_DURATION" + "from test | where x < ?0 and y < ?2", + List.of(new QueryParam(null, 5, INTEGER)), + "line 1:24: No parameter is defined for position 0, did you mean position 1?; " + + "line 1:35: No parameter is defined for position 2, did you mean position 1?" ); expectError( - "row x = ?", - List.of(new TypedParamValue("date_period", "2 minutes")), - "Cannot parse [2 minutes] to DATE_PERIOD, did you mean TIME_DURATION?" + "from test | where x < ?0 and y < ?2", + List.of(new QueryParam(null, 5, INTEGER)), + "No parameter is defined for position 2, did you mean position 1" ); + expectError( - "row x = ?", - List.of(new TypedParamValue("time_duration", "11 months")), - "Cannot parse [11 months] to TIME_DURATION, did you mean DATE_PERIOD?" + "from test | where x < ?0", + List.of(new QueryParam(null, 5, INTEGER), new QueryParam(null, 10, INTEGER)), + "No parameter is defined for position 0, did you mean any position between 1 and 2?" ); } - public void testMissingInputParams() { - expectError("row x = ?, y = ?", List.of(new TypedParamValue("integer", 1)), "Not enough actual parameters 1"); + public void testParamInWhere() { + LogicalPlan plan = statement("from test | where x < ? | limit 10", new QueryParams(List.of(new QueryParam(null, 5, INTEGER)))); + assertThat(plan, instanceOf(Limit.class)); + Limit limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Filter.class)); + Filter w = (Filter) limit.children().get(0); + assertThat(((Literal) w.condition().children().get(1)).value(), equalTo(5)); + assertThat(limit.children().get(0).children().size(), equalTo(1)); + assertThat(limit.children().get(0).children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement("from test | where x < ?n1 | limit 10", new QueryParams(List.of(new QueryParam("n1", 5, INTEGER)))); + assertThat(plan, instanceOf(Limit.class)); + limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Filter.class)); + w = (Filter) limit.children().get(0); + assertThat(((Literal) w.condition().children().get(1)).value(), equalTo(5)); + assertThat(limit.children().get(0).children().size(), equalTo(1)); + assertThat(limit.children().get(0).children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement("from test | where x < ?1 | limit 10", new QueryParams(List.of(new QueryParam(null, 5, INTEGER)))); + assertThat(plan, instanceOf(Limit.class)); + limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Filter.class)); + w = (Filter) limit.children().get(0); + assertThat(((Literal) w.condition().children().get(1)).value(), equalTo(5)); + assertThat(limit.children().get(0).children().size(), equalTo(1)); + assertThat(limit.children().get(0).children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + } + + public void testParamInEval() { + LogicalPlan plan = statement( + "from test | where x < ? | eval y = ? + ? | limit 10", + new QueryParams( + List.of(new QueryParam(null, 5, INTEGER), new QueryParam(null, -1, INTEGER), new QueryParam(null, 100, INTEGER)) + ) + ); + assertThat(plan, instanceOf(Limit.class)); + Limit limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Eval.class)); + Eval eval = (Eval) limit.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(100)); + Filter f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement( + "from test | where x < ?n1 | eval y = ?n2 + ?n3 | limit 10", + new QueryParams( + List.of(new QueryParam("n1", 5, INTEGER), new QueryParam("n2", -1, INTEGER), new QueryParam("n3", 100, INTEGER)) + ) + ); + assertThat(plan, instanceOf(Limit.class)); + limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Eval.class)); + eval = (Eval) limit.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(100)); + f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement( + "from test | where x < ?1 | eval y = ?2 + ?1 | limit 10", + new QueryParams(List.of(new QueryParam(null, 5, INTEGER), new QueryParam(null, -1, INTEGER))) + ); + assertThat(plan, instanceOf(Limit.class)); + limit = (Limit) plan; + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(10)); + assertThat(limit.children().size(), equalTo(1)); + assertThat(limit.children().get(0), instanceOf(Eval.class)); + eval = (Eval) limit.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(5)); + f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + } + + public void testParamInAggFunction() { + LogicalPlan plan = statement( + "from test | where x < ? | eval y = ? + ? | stats count(?) by z", + new QueryParams( + List.of( + new QueryParam(null, 5, INTEGER), + new QueryParam(null, -1, INTEGER), + new QueryParam(null, 100, INTEGER), + new QueryParam(null, "*", KEYWORD) + ) + ) + ); + assertThat(plan, instanceOf(EsqlAggregate.class)); + EsqlAggregate agg = (EsqlAggregate) plan; + assertThat(((Literal) agg.aggregates().get(0).children().get(0).children().get(0)).value(), equalTo("*")); + assertThat(agg.child(), instanceOf(Eval.class)); + assertThat(agg.children().size(), equalTo(1)); + assertThat(agg.children().get(0), instanceOf(Eval.class)); + Eval eval = (Eval) agg.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(100)); + Filter f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement( + "from test | where x < ?n1 | eval y = ?n2 + ?n3 | stats count(?n4) by z", + new QueryParams( + List.of( + new QueryParam("n1", 5, INTEGER), + new QueryParam("n2", -1, INTEGER), + new QueryParam("n3", 100, INTEGER), + new QueryParam("n4", "*", KEYWORD) + ) + ) + ); + assertThat(plan, instanceOf(EsqlAggregate.class)); + agg = (EsqlAggregate) plan; + assertThat(((Literal) agg.aggregates().get(0).children().get(0).children().get(0)).value(), equalTo("*")); + assertThat(agg.child(), instanceOf(Eval.class)); + assertThat(agg.children().size(), equalTo(1)); + assertThat(agg.children().get(0), instanceOf(Eval.class)); + eval = (Eval) agg.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(100)); + f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + + plan = statement( + "from test | where x < ?1 | eval y = ?2 + ?1 | stats count(?3) by z", + new QueryParams( + List.of(new QueryParam(null, 5, INTEGER), new QueryParam(null, -1, INTEGER), new QueryParam(null, "*", KEYWORD)) + ) + ); + assertThat(plan, instanceOf(EsqlAggregate.class)); + agg = (EsqlAggregate) plan; + assertThat(((Literal) agg.aggregates().get(0).children().get(0).children().get(0)).value(), equalTo("*")); + assertThat(agg.child(), instanceOf(Eval.class)); + assertThat(agg.children().size(), equalTo(1)); + assertThat(agg.children().get(0), instanceOf(Eval.class)); + eval = (Eval) agg.children().get(0); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).left()).value(), equalTo(-1)); + assertThat(((Literal) ((Add) eval.fields().get(0).child()).right()).value(), equalTo(5)); + f = (Filter) eval.children().get(0); + assertThat(((Literal) f.condition().children().get(1)).value(), equalTo(5)); + assertThat(f.children().size(), equalTo(1)); + assertThat(f.children().get(0), instanceOf(EsqlUnresolvedRelation.class)); + } + + public void testParamMixed() { + expectError( + "from test | where x < ? | eval y = ?n2 + ?n3 | limit ?n4", + List.of( + new QueryParam("n1", 5, INTEGER), + new QueryParam("n2", -1, INTEGER), + new QueryParam("n3", 100, INTEGER), + new QueryParam("n4", 10, INTEGER) + ), + "Inconsistent parameter declaration, " + + "use one of positional, named or anonymous params but not a combination of named and anonymous" + ); + + expectError( + "from test | where x < ?1 | eval y = ?n2 + ?n3 | limit ?n4", + List.of( + new QueryParam("n1", 5, INTEGER), + new QueryParam("n2", -1, INTEGER), + new QueryParam("n3", 100, INTEGER), + new QueryParam("n4", 10, INTEGER) + ), + "Inconsistent parameter declaration, " + + "use one of positional, named or anonymous params but not a combination of named and positional" + ); + + expectError( + "from test | where x < ? | eval y = ?2 + ?n3 | limit ?n4", + List.of( + new QueryParam("n1", 5, INTEGER), + new QueryParam("n2", -1, INTEGER), + new QueryParam("n3", 100, INTEGER), + new QueryParam("n4", 10, INTEGER) + ), + "Inconsistent parameter declaration, " + + "use one of positional, named or anonymous params but not a combination of positional and anonymous" + ); } public void testFieldContainingDotsAndNumbers() { @@ -1117,10 +1399,10 @@ private void assertStatement(String statement, LogicalPlan expected) { } private LogicalPlan statement(String e) { - return statement(e, List.of()); + return statement(e, QueryParams.EMPTY); } - private LogicalPlan statement(String e, List params) { + private LogicalPlan statement(String e, QueryParams params) { return parser.createStatement(e, params); } @@ -1200,8 +1482,12 @@ private void expectVerificationError(String query, String errorMessage) { assertThat(e.getMessage(), containsString(errorMessage)); } - private void expectError(String query, List params, String errorMessage) { - ParsingException e = expectThrows(ParsingException.class, "Expected syntax error for " + query, () -> statement(query, params)); + private void expectError(String query, List params, String errorMessage) { + ParsingException e = expectThrows( + ParsingException.class, + "Expected syntax error for " + query, + () -> statement(query, new QueryParams(params)) + ); assertThat(e.getMessage(), containsString(errorMessage)); } } diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml index ab0261d916630..1c95e961d0535 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/10_basic.yml @@ -309,12 +309,12 @@ setup: - match: {values.0: [1, 44, "green"]} --- -"Test Mixed Input Params": +"Test Unnamed Input Params": - do: esql.query: body: query: 'from test | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit 3' - params: [{"value": 1, "type": "keyword"}, {"value": 2, "type": "double"}, null, true, 123, {"value": 123, "type": "long"}] + params: ["1", 2.0, null, true, 123, 1674835275193] - length: {columns: 6} - match: {columns.0.name: "x"} @@ -330,9 +330,44 @@ setup: - match: {columns.5.name: "v"} - match: {columns.5.type: "long"} - length: {values: 3} - - match: {values.0: ["1",2.0,null,true,123,123]} - - match: {values.1: ["1",2.0,null,true,123,123]} - - match: {values.2: ["1",2.0,null,true,123,123]} + - match: {values.0: ["1",2.0,null,true,123,1674835275193]} + - match: {values.1: ["1",2.0,null,true,123,1674835275193]} + - match: {values.2: ["1",2.0,null,true,123,1674835275193]} + +--- +"Test Named Input Params": + - requires: + test_runner_features: [ capabilities ] + capabilities: + - method: POST + path: /_query + parameters: [ ] + capabilities: [ named_positional_parameter ] + reason: "named or positional parameters" + + - do: + esql.query: + body: + query: 'from test | eval x = ?, y = ?, z = ?, t = ?, u = ?, v = ? | keep x, y, z, t, u, v | limit 3' + params: [{"n1" : "1"}, {"n2" : 2.0}, {"n3" : null}, {"n4" : true}, {"n5" : 123}, {"n6": 1674835275193}] + + - length: {columns: 6} + - match: {columns.0.name: "x"} + - match: {columns.0.type: "keyword"} + - match: {columns.1.name: "y"} + - match: {columns.1.type: "double"} + - match: {columns.2.name: "z"} + - match: {columns.2.type: "null"} + - match: {columns.3.name: "t"} + - match: {columns.3.type: "boolean"} + - match: {columns.4.name: "u"} + - match: {columns.4.type: "integer"} + - match: {columns.5.name: "v"} + - match: {columns.5.type: "long"} + - length: {values: 3} + - match: {values.0: ["1",2.0,null,true,123,1674835275193]} + - match: {values.1: ["1",2.0,null,true,123,1674835275193]} + - match: {values.2: ["1",2.0,null,true,123,1674835275193]} --- version is not allowed: From 394d2b09a675603ff4255e9bf114eccec75db975 Mon Sep 17 00:00:00 2001 From: Liam Thompson <32779855+leemthompo@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:04:37 +0200 Subject: [PATCH 16/18] Revert "[DOCS] Remove ESQL demo env link from 8.14+ (#109562)" (#109579) This reverts commit 0480c1acba41cb0cd8fb22c384adfff0790a2f85. --- docs/reference/esql/esql-get-started.asciidoc | 8 ++++---- .../esql/esql-getting-started-sample-data.asciidoc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference/esql/esql-get-started.asciidoc b/docs/reference/esql/esql-get-started.asciidoc index 207794c064da4..b7928898a3bbb 100644 --- a/docs/reference/esql/esql-get-started.asciidoc +++ b/docs/reference/esql/esql-get-started.asciidoc @@ -15,9 +15,10 @@ This getting started is also available as an https://github.com/elastic/elastics [[esql-getting-started-prerequisites]] === Prerequisites -To follow along with the queries in this guide, you'll need an {es} deployment with our sample data. +To follow along with the queries in this guide, you can either set up your own +deployment, or use Elastic's public {esql} demo environment. -include::{es-ref-dir}/tab-widgets/esql/esql-getting-started-sample-data.asciidoc[tag=own-deployment] +include::{es-ref-dir}/tab-widgets/esql/esql-getting-started-widget-sample-data.asciidoc[] [discrete] [[esql-getting-started-running-queries]] @@ -268,8 +269,7 @@ Before you can use `ENRICH`, you first need to <> and <> an <>. -include::{es-ref-dir}/tab-widgets/esql/esql-getting-started-enrich-policy.asciidoc[tag=own-deployment] - +include::{es-ref-dir}/tab-widgets/esql/esql-getting-started-widget-enrich-policy.asciidoc[] After creating and executing a policy, you can use it with the `ENRICH` command: diff --git a/docs/reference/tab-widgets/esql/esql-getting-started-sample-data.asciidoc b/docs/reference/tab-widgets/esql/esql-getting-started-sample-data.asciidoc index 97f4859e012af..d9b08b7281f77 100644 --- a/docs/reference/tab-widgets/esql/esql-getting-started-sample-data.asciidoc +++ b/docs/reference/tab-widgets/esql/esql-getting-started-sample-data.asciidoc @@ -1,6 +1,6 @@ // tag::own-deployment[] -First, you'll need to ingest the sample data. In {kib}, open the main menu and select *Dev +First ingest some sample data. In {kib}, open the main menu and select *Dev Tools*. Run the following two requests: [source,console] From 2a193b53d84b65395003e5be9cb5502c764be8e4 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 11 Jun 2024 17:23:25 +0100 Subject: [PATCH 17/18] Remove unused `BaseNodesRequest` broadcasts (#109512) Several `TransportNodesAction` implementations send the top-level request out to every node even though the nodes themselves don't use it. This commit adjusts the transport protocol to drop the unnecessary data on the wire. Relates #100878 --- .../org/elasticsearch/TransportVersions.java | 1 + .../cluster/node/info/NodesInfoRequest.java | 3 +++ .../cluster/node/stats/NodesStatsRequest.java | 4 +++- .../cluster/stats/ClusterStatsRequest.java | 3 +++ .../stats/TransportClusterStatsAction.java | 20 ++++++++++--------- .../node/tasks/CancellableTasksTests.java | 9 ++------- .../node/tasks/TaskManagerTestCase.java | 1 - .../cluster/node/tasks/TestTaskPlugin.java | 10 +--------- .../node/tasks/TransportTasksActionTests.java | 7 +------ .../nodes/TransportNodesActionTests.java | 8 -------- .../action/GetInferenceDiagnosticsAction.java | 4 ---- .../action/TrainedModelCacheInfoAction.java | 3 +++ .../NodesDeprecationCheckAction.java | 18 +++++++++-------- .../NodesDeprecationCheckRequest.java | 4 ++++ .../TransportNodeDeprecationCheckAction.java | 2 +- .../TransportTrainedModelCacheInfoAction.java | 19 ++++++++++-------- 16 files changed, 54 insertions(+), 62 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/TransportVersions.java b/server/src/main/java/org/elasticsearch/TransportVersions.java index c2be2da12534b..e85209c19d827 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -188,6 +188,7 @@ static TransportVersion def(int id) { public static final TransportVersion RANK_DOC_IN_SHARD_FETCH_REQUEST = def(8_679_00_0); public static final TransportVersion SECURITY_SETTINGS_REQUEST_TIMEOUTS = def(8_680_00_0); public static final TransportVersion QUERY_RULE_CRUD_API_PUT = def(8_681_00_0); + public static final TransportVersion DROP_UNUSED_NODES_REQUESTS = def(8_682_00_0); /* * STOP! READ THIS FIRST! No, really, diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoRequest.java index ebf01feaaa891..51699c1f7dcd3 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoRequest.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import java.io.IOException; import java.util.Set; @@ -30,6 +31,7 @@ public final class NodesInfoRequest extends BaseNodesRequest { * @param in A stream input object. * @throws IOException if the stream cannot be deserialized. */ + @UpdateForV9 // this constructor is unused in v9 public NodesInfoRequest(StreamInput in) throws IOException { super(in); nodesInfoMetrics = new NodesInfoMetrics(in); @@ -111,6 +113,7 @@ public NodesInfoRequest removeMetric(String metric) { return this; } + @UpdateForV9 // this method can just call localOnly() in v9 @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java index c441c6daf89bf..ff88bc5fcf464 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.tasks.CancellableTask; import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.TaskId; @@ -36,9 +37,9 @@ public NodesStatsRequest() { nodesStatsRequestParameters = new NodesStatsRequestParameters(); } + @UpdateForV9 // this constructor is unused in v9 public NodesStatsRequest(StreamInput in) throws IOException { super(in); - nodesStatsRequestParameters = new NodesStatsRequestParameters(in); } @@ -178,6 +179,7 @@ public void setIncludeShardsStats(boolean includeShardsStats) { nodesStatsRequestParameters.setIncludeShardsStats(includeShardsStats); } + @UpdateForV9 // this method can just call localOnly() in v9 @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsRequest.java index ca2ec4e5607e3..bba669e07a70c 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsRequest.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.tasks.CancellableTask; import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.TaskId; @@ -23,6 +24,7 @@ */ public class ClusterStatsRequest extends BaseNodesRequest { + @UpdateForV9 // this constructor is unused in v9 public ClusterStatsRequest(StreamInput in) throws IOException { super(in); } @@ -40,6 +42,7 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, return new CancellableTask(id, type, action, "", parentTaskId, headers); } + @UpdateForV9 // this method can just call localOnly() in v9 @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java index f1b6faaca439a..2a8fecde7ee9e 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java @@ -9,6 +9,7 @@ package org.elasticsearch.action.admin.cluster.stats; import org.apache.lucene.store.AlreadyClosedException; +import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionType; import org.elasticsearch.action.FailedNodeException; @@ -32,6 +33,7 @@ import org.elasticsearch.common.util.CancellableSingleObjectCache; import org.elasticsearch.common.util.concurrent.ListenableFuture; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.engine.CommitStats; import org.elasticsearch.index.seqno.RetentionLeaseStats; @@ -167,7 +169,7 @@ protected ClusterStatsResponse newResponse( @Override protected ClusterStatsNodeRequest newNodeRequest(ClusterStatsRequest request) { - return new ClusterStatsNodeRequest(request); + return new ClusterStatsNodeRequest(); } @Override @@ -251,18 +253,16 @@ protected ClusterStatsNodeResponse nodeOperation(ClusterStatsNodeRequest nodeReq ); } + @UpdateForV9 // this can be replaced with TransportRequest.Empty in v9 public static class ClusterStatsNodeRequest extends TransportRequest { - // TODO don't wrap the whole top-level request, it contains heavy and irrelevant DiscoveryNode things; see #100878 - ClusterStatsRequest request; + ClusterStatsNodeRequest() {} public ClusterStatsNodeRequest(StreamInput in) throws IOException { super(in); - request = new ClusterStatsRequest(in); - } - - ClusterStatsNodeRequest(ClusterStatsRequest request) { - this.request = request; + if (in.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new ClusterStatsRequest(in); + } } @Override @@ -273,7 +273,9 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - request.writeTo(out); + if (out.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new ClusterStatsRequest().writeTo(out); + } } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/CancellableTasksTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/CancellableTasksTests.java index 22953f9959c1d..9883eec6896ce 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/CancellableTasksTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/CancellableTasksTests.java @@ -100,12 +100,7 @@ public boolean shouldCancelChildrenOnCancellation() { } public static class CancellableNodesRequest extends BaseNodesRequest { - private String requestName; - - private CancellableNodesRequest(StreamInput in) throws IOException { - super(in); - requestName = in.readString(); - } + private final String requestName; public CancellableNodesRequest(String requestName, String... nodesIds) { super(nodesIds); @@ -147,7 +142,7 @@ class CancellableTestNodesAction extends AbstractTestNodesAction request, Writeable.Reader nodeRequest ) { super( diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TestTaskPlugin.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TestTaskPlugin.java index 63629e16974d5..6f345eb7dcdab 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TestTaskPlugin.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TestTaskPlugin.java @@ -195,19 +195,11 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, } public static class NodesRequest extends BaseNodesRequest { - private String requestName; + private final String requestName; private boolean shouldStoreResult = false; private boolean shouldBlock = true; private boolean shouldFail = false; - NodesRequest(StreamInput in) throws IOException { - super(in); - requestName = in.readString(); - shouldStoreResult = in.readBoolean(); - shouldBlock = in.readBoolean(); - shouldFail = in.readBoolean(); - } - NodesRequest(String requestName, String... nodesIds) { super(nodesIds); this.requestName = requestName; diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java index 6f4da1fe1ebe0..969ed50685bc2 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java @@ -109,11 +109,6 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, public static class NodesRequest extends BaseNodesRequest { private final String requestName; - NodesRequest(StreamInput in) throws IOException { - super(in); - requestName = in.readString(); - } - public NodesRequest(String requestName, String... nodesIds) { super(nodesIds); this.requestName = requestName; @@ -142,7 +137,7 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, abstract class TestNodesAction extends AbstractTestNodesAction { TestNodesAction(String actionName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService) { - super(actionName, threadPool, clusterService, transportService, NodesRequest::new, NodeRequest::new); + super(actionName, threadPool, clusterService, transportService, NodeRequest::new); } @Override diff --git a/server/src/test/java/org/elasticsearch/action/support/nodes/TransportNodesActionTests.java b/server/src/test/java/org/elasticsearch/action/support/nodes/TransportNodesActionTests.java index 689040f9b6c54..d0535665d3685 100644 --- a/server/src/test/java/org/elasticsearch/action/support/nodes/TransportNodesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/support/nodes/TransportNodesActionTests.java @@ -323,11 +323,9 @@ public TestTransportNodesAction getTestTransportNodesAction() { public DataNodesOnlyTransportNodesAction getDataNodesOnlyTransportNodesAction(TransportService transportService) { return new DataNodesOnlyTransportNodesAction( - THREAD_POOL, clusterService, transportService, new ActionFilters(Collections.emptySet()), - TestNodesRequest::new, TestNodeRequest::new, THREAD_POOL.executor(ThreadPool.Names.GENERIC) ); @@ -383,11 +381,9 @@ protected TestNodeResponse nodeOperation(TestNodeRequest request, Task task) { private static class DataNodesOnlyTransportNodesAction extends TestTransportNodesAction { DataNodesOnlyTransportNodesAction( - ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters, - Writeable.Reader request, Writeable.Reader nodeRequest, Executor nodeExecutor ) { @@ -401,10 +397,6 @@ protected void resolveRequest(TestNodesRequest request, ClusterState clusterStat } private static class TestNodesRequest extends BaseNodesRequest { - TestNodesRequest(StreamInput in) throws IOException { - super(in); - } - TestNodesRequest(String... nodesIds) { super(nodesIds); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/GetInferenceDiagnosticsAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/GetInferenceDiagnosticsAction.java index 29edc88ecda70..00dcd56424016 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/GetInferenceDiagnosticsAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/GetInferenceDiagnosticsAction.java @@ -43,10 +43,6 @@ public Request() { super((String[]) null); } - public Request(StreamInput in) throws IOException { - super(in); - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/TrainedModelCacheInfoAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/TrainedModelCacheInfoAction.java index 81a0a95c9f8ba..2cbf577790b37 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/TrainedModelCacheInfoAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/TrainedModelCacheInfoAction.java @@ -18,6 +18,7 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.unit.ByteSizeValue; +import org.elasticsearch.core.UpdateForV9; import java.io.IOException; import java.util.Arrays; @@ -39,10 +40,12 @@ public Request(DiscoveryNode... concreteNodes) { super(concreteNodes); } + @UpdateForV9 // this constructor is unused in v9 public Request(StreamInput in) throws IOException { super(in); } + @UpdateForV9 // this method can just call localOnly() in v9 @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckAction.java b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckAction.java index 89b0e97e2be28..c867ef671811c 100644 --- a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckAction.java +++ b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckAction.java @@ -7,11 +7,13 @@ package org.elasticsearch.xpack.deprecation; +import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionType; import org.elasticsearch.action.support.nodes.BaseNodeResponse; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.core.deprecation.DeprecationIssue; @@ -31,24 +33,24 @@ private NodesDeprecationCheckAction() { super(NAME); } + @UpdateForV9 // this can be replaced with TransportRequest.Empty in v9 public static class NodeRequest extends TransportRequest { - // TODO don't wrap the whole top-level request, it contains heavy and irrelevant DiscoveryNode things; see #100878 - NodesDeprecationCheckRequest request; + public NodeRequest() {} public NodeRequest(StreamInput in) throws IOException { super(in); - request = new NodesDeprecationCheckRequest(in); - } - - public NodeRequest(NodesDeprecationCheckRequest request) { - this.request = request; + if (in.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new NodesDeprecationCheckRequest(in); + } } @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - request.writeTo(out); + if (out.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new NodesDeprecationCheckRequest().writeTo(out); + } } } diff --git a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckRequest.java b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckRequest.java index 136fa12d53335..2e5f77ee52778 100644 --- a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckRequest.java +++ b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodesDeprecationCheckRequest.java @@ -10,12 +10,15 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import java.io.IOException; import java.util.Arrays; import java.util.Objects; public class NodesDeprecationCheckRequest extends BaseNodesRequest { + + @UpdateForV9 // this constructor is unused in v9 public NodesDeprecationCheckRequest(StreamInput in) throws IOException { super(in); } @@ -24,6 +27,7 @@ public NodesDeprecationCheckRequest(String... nodesIds) { super(nodesIds); } + @UpdateForV9 // this method can just call localOnly() in v9 @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportNodeDeprecationCheckAction.java b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportNodeDeprecationCheckAction.java index 34558c289b555..ba72be655a7ff 100644 --- a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportNodeDeprecationCheckAction.java +++ b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportNodeDeprecationCheckAction.java @@ -95,7 +95,7 @@ protected NodesDeprecationCheckResponse newResponse( @Override protected NodesDeprecationCheckAction.NodeRequest newNodeRequest(NodesDeprecationCheckRequest request) { - return new NodesDeprecationCheckAction.NodeRequest(request); + return new NodesDeprecationCheckAction.NodeRequest(); } @Override diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportTrainedModelCacheInfoAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportTrainedModelCacheInfoAction.java index 89eb1dc45c547..f2c2b6de0e19d 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportTrainedModelCacheInfoAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportTrainedModelCacheInfoAction.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.ml.action; +import org.elasticsearch.TransportVersions; import org.elasticsearch.action.FailedNodeException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.nodes.TransportNodesAction; @@ -15,6 +16,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.tasks.CancellableTask; import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.TaskId; @@ -67,7 +69,7 @@ protected TrainedModelCacheInfoAction.Response newResponse( @Override protected NodeModelCacheInfoRequest newNodeRequest(TrainedModelCacheInfoAction.Request request) { - return new NodeModelCacheInfoRequest(request); + return new NodeModelCacheInfoRequest(); } @Override @@ -85,17 +87,16 @@ protected CacheInfo nodeOperation(NodeModelCacheInfoRequest nodeModelCacheInfoRe ); } + @UpdateForV9 // this can be replaced with TransportRequest.Empty in v9 public static class NodeModelCacheInfoRequest extends TransportRequest { - TrainedModelCacheInfoAction.Request request; + NodeModelCacheInfoRequest() {} public NodeModelCacheInfoRequest(StreamInput in) throws IOException { super(in); - request = new TrainedModelCacheInfoAction.Request(in); - } - - NodeModelCacheInfoRequest(TrainedModelCacheInfoAction.Request request) { - this.request = request; + if (in.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new TrainedModelCacheInfoAction.Request(in); + } } @Override @@ -106,7 +107,9 @@ public Task createTask(long id, String type, String action, TaskId parentTaskId, @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - request.writeTo(out); + if (out.getTransportVersion().before(TransportVersions.DROP_UNUSED_NODES_REQUESTS)) { + new TrainedModelCacheInfoAction.Request().writeTo(out); + } } } } From 6d7c9a0d19ef7506d1463dfa13cba37842e2e302 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 11 Jun 2024 17:34:16 +0100 Subject: [PATCH 18/18] Deprecate `BaseNodesRequest` reader ctor (#109513) Relates #100878 --- .../action/support/nodes/BaseNodesRequest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/action/support/nodes/BaseNodesRequest.java b/server/src/main/java/org/elasticsearch/action/support/nodes/BaseNodesRequest.java index 8a2e7684cadfa..626cdb8046f53 100644 --- a/server/src/main/java/org/elasticsearch/action/support/nodes/BaseNodesRequest.java +++ b/server/src/main/java/org/elasticsearch/action/support/nodes/BaseNodesRequest.java @@ -39,6 +39,14 @@ public abstract class BaseNodesRequest private TimeValue timeout; + /** + * @deprecated {@link BaseNodesRequest} derivatives are quite heavyweight and should never need sending over the wire. Do not include + * the full top-level request directly in the node-level requests. Instead, copy the needed fields over to a dedicated node-level + * request. + * + * @see #100878 + */ + @Deprecated(forRemoval = true) protected BaseNodesRequest(StreamInput in) throws IOException { // A bare `BaseNodesRequest` is never sent over the wire, but several implementations send the full top-level request to each node // (wrapped up in another request). They shouldn't, but until we fix that we must keep this. See #100878.