From 90ab2558b03f59c38b8223c2b881f97da7cd4394 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 11 Jun 2024 08:07:40 -0400 Subject: [PATCH 01/34] 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 be1e619d046a..c4d8b1f0929b 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 02/34] 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 d82c823f664b..eeafea033fc8 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 03/34] [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 e0d01965479c..7dd9d0574638 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 04/34] 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 ff22334462fd..000000000000 --- 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 91277fa8dd65..000000000000 --- 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 02c39a69bc9b..000000000000 --- 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 4cc30a99d92f..000000000000 --- 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 629fe7392c12..000000000000 --- 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 4b3add76282d..000000000000 --- 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 a3969479d091..000000000000 --- 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 b2f9aa7b5d23..000000000000 --- 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 31208905f7d7..000000000000 --- 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 021d9f8d01bf..000000000000 --- 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: - *
    - *
  • A transaction for the REST API call - *
  • A span for the task started by the REST call - *
  • A child span started by the above span - *
- *

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 05/34] 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 eeafea033fc8..706a59882a20 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 06/34] [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 5ca285677a95..a58f2399301d 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 e5314a20bdcc..bb03d3c69c74 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.xcontent.XContentType; 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 @@ public class ConnectorIndexService { /** * 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 7c279852625b..d71344e74aee 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 @@ public class TransportUpdateConnectorErrorAction extends HandledTransportAction< 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 e6485285e199..ae86c1fc98df 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.io.IOException; 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 class UpdateConnectorErrorAction { ); 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 698c061d1bd6..a696c6e6dde5 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 class ConnectorIndexServiceTests extends ESSingleNodeTestCase { 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 @@ public class ConnectorIndexServiceTests extends ESSingleNodeTestCase { 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 07/34] 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 5507c6cc29d1..88f7570f753c 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 7c57212d0f57..bf54dcbfa96f 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 class RestEsqlIT extends RestEsqlTestCase { 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 a42f02a22aba..3e7b1e927a9b 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 abstract class EsqlSpecTestCase extends ESRestTestCase { * "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 349f9445030c..0c5ec5eac716 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 @@ public abstract class RestEsqlTestCase extends ESRestTestCase { 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 abstract class RestEsqlTestCase extends ESRestTestCase { return this; } - public RequestObjectBuilder tables(Map>> tables) { + public RequestObjectBuilder tables(Map> tables) { this.tables = tables; return this; } @@ -181,7 +183,17 @@ public abstract class RestEsqlTestCase extends ESRestTestCase { 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 75600e64e3e9..9e8553911268 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 97728196a0ce..cc56285f3c78 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 @@ public class ParseTables { 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 @@ public class ParseTables { } } - 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 b78958152b17..ab0bc114a276 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { "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 dcffca2f28fb..5f76954e57c8 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 08/34] 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 7bffba0a1957..e5b8f8d8622c 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 88f7570f753c..1944d243968a 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 706a59882a20..4f4d6da837a8 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 09/34] [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 5636762871b2..87fad19ab87f 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 class PyTorchResultProcessor { } 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 dee608e69f5b..debe6586e453 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.AtomicBoolean; 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 abstract class AbstractProcessWorkerExecutorService e 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 10/34] 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 61e5c1bfcc81..6b2c7f0a9580 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.SortField; 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 class ShrinkIndexIT extends ESIntegTestCase { 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 770ca21fd689..8a239f7293e2 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 @@ package org.elasticsearch.cluster; 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 class SimpleDataNodesIT extends ESIntegTestCase { 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 e6ea4823e86f..71418cb83deb 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 @@ package org.elasticsearch.cluster.allocation; 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 class AwarenessAllocationIT extends ESIntegTestCase { .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 class AwarenessAllocationIT extends ESIntegTestCase { .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 bacff31b480e..5f75b62cabb6 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 @@ package org.elasticsearch.cluster.allocation; 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 @@ public class ClusterRerouteIT extends ESIntegTestCase { 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 @@ public class ClusterRerouteIT extends ESIntegTestCase { 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 @@ public class ClusterRerouteIT extends ESIntegTestCase { ); 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 @@ public class ClusterRerouteIT extends ESIntegTestCase { 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 @@ public class ClusterRerouteIT extends ESIntegTestCase { 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 class ClusterRerouteIT extends ESIntegTestCase { 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 class ClusterRerouteIT extends ESIntegTestCase { ); 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 class ClusterRerouteIT extends ESIntegTestCase { 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 class ClusterRerouteIT extends ESIntegTestCase { )) { 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 class ClusterRerouteIT extends ESIntegTestCase { 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 ae79c388aa10..5f54b32ab4a1 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 class FilteringAllocationIT extends ESIntegTestCase { } 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 class FilteringAllocationIT extends ESIntegTestCase { 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 a25de555ce26..8cee57ee34b8 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 @@ package org.elasticsearch.cluster.routing; 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 class AllocationIdIT extends ESIntegTestCase { 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 class AllocationIdIT extends ESIntegTestCase { 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 72594fef8c6e..db84f2a0a34d 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 @@ public class PrimaryAllocationIT extends ESIntegTestCase { 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 class PrimaryAllocationIT extends ESIntegTestCase { ); 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 class PrimaryAllocationIT extends ESIntegTestCase { 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 class PrimaryAllocationIT extends ESIntegTestCase { 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 class PrimaryAllocationIT extends ESIntegTestCase { .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 class PrimaryAllocationIT extends ESIntegTestCase { 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 class PrimaryAllocationIT extends ESIntegTestCase { 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 76311387115d..bb9324dd7d10 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 @@ package org.elasticsearch.cluster.routing; 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 class ShardRoutingRoleIT extends ESIntegTestCase { 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 8499bc8aef4a..16be816b69bc 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 @@ public class DiskThresholdDeciderIT extends DiskUsageIntegTestCase { .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 da1156953e26..921ed3265f1b 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 class UpdateShardAllocationSettingsIT extends ESIntegTestCase { .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 class UpdateShardAllocationSettingsIT extends ESIntegTestCase { "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 class UpdateShardAllocationSettingsIT extends ESIntegTestCase { ) ); 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 cd9adea500db..a0fa63aa58ab 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.ElasticsearchException; 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 class ClusterDisruptionIT extends AbstractDisruptionTestCase { // 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 af254d42ec3e..3e7e4d47e7a2 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 class MasterDisruptionIT extends AbstractDisruptionTestCase { 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 ef4616fdd0b4..bdfe629f4bab 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.LockObtainFailedException; 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 class RemoveCorruptedShardDataCommandIT extends ESIntegTestCase { ); }); - 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 class RemoveCorruptedShardDataCommandIT extends ESIntegTestCase { ); }); - 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 7e3df8d8e1cb..2fed0a45032a 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.ElasticsearchException; 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 class CorruptedFileIT extends ESIntegTestCase { * 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 class CorruptedFileIT extends ESIntegTestCase { .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 class CorruptedFileIT extends ESIntegTestCase { .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 28a5ad9c2912..5c4cdc8cde85 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 @@ package org.elasticsearch.indexlifecycle; 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 class IndexLifecycleActionIT extends ESIntegTestCase { 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 class IndexLifecycleActionIT extends ESIntegTestCase { 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 class IndexLifecycleActionIT extends ESIntegTestCase { 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 d5cbb215781b..b224d70eed8f 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 class IndicesLifecycleListenerIT extends ESIntegTestCase { 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 874ba7b42690..28e89f459055 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 @@ package org.elasticsearch.indices.cluster; 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 org.elasticsearch.test.junit.annotations.TestLogging; 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 class ShardLockFailureIT extends ESIntegTestCase { 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 779072272e59..a9e06fe438c4 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 @@ package org.elasticsearch.indices.recovery; 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 class IndexPrimaryRelocationIT extends ESIntegTestCase { 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 23963fe50aa4..14b13addac84 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.ActionListener; 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 @@ public class IndexRecoveryIT extends AbstractIndexRecoveryIntegTestCase { */ 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 class IndexRecoveryIT extends AbstractIndexRecoveryIntegTestCase { 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 class IndexRecoveryIT extends AbstractIndexRecoveryIntegTestCase { 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 class IndexRecoveryIT extends AbstractIndexRecoveryIntegTestCase { 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 class IndexRecoveryIT extends AbstractIndexRecoveryIntegTestCase { ); 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 b66a0b0f3be4..b160834d675d 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 class CloseWhileRelocatingShardsIT extends ESIntegTestCase { 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 class CloseWhileRelocatingShardsIT extends ESIntegTestCase { } // 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 class CloseWhileRelocatingShardsIT extends ESIntegTestCase { } } - 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 5805eab83123..5eeb07968ce4 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 @@ package org.elasticsearch.indices.store; 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 class IndicesStoreIntegrationIT extends ESIntegTestCase { 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 class IndicesStoreIntegrationIT extends ESIntegTestCase { } } }); - 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 class IndicesStoreIntegrationIT extends ESIntegTestCase { }); 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 4c3c05992a44..f0026dfa0a34 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.apache.lucene.tests.util.English; 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 class RelocationIT extends ESIntegTestCase { 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 class RelocationIT extends ESIntegTestCase { 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 class RelocationIT extends ESIntegTestCase { 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 class RelocationIT extends ESIntegTestCase { 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 class RelocationIT extends ESIntegTestCase { 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 class RelocationIT extends ESIntegTestCase { .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 03a21210630b..657158327bf0 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 @@ package org.elasticsearch.search.basic; 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 class SearchWhileRelocatingIT extends ESIntegTestCase { 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 ae3347dafd55..9d3ce1c99b55 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.http.entity.StringEntity; 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 @@ public class FieldCapabilitiesIT extends ESIntegTestCase { 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 6e19cf60cf5b..d625b53785d3 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.apache.lucene.util.BytesRef; 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 class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas 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 2204fd08ae58..4bfa3505667d 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 @@ import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand; /** * 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 d2ac07cf1647..4f24aa7b93f4 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 class ClusterAdminClient implements ElasticsearchClient { 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 769877ac943e..47d6198114fc 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 class RestClusterRerouteAction extends BaseRestHandler { 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 dc0bd57731d9..2ed69810c890 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 @@ package org.elasticsearch.client.internal; 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 abstract class AbstractClientHeadersTestCase extends ESTestCase { .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 40064e2b68ed..8a5d282fe014 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 class SnapshotResiliencyTests extends ESTestCase { .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 000000000000..3da245ec430a --- /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 bf9eba87ee80..49c244167fe1 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 java.util.function.Consumer; 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 class ElasticsearchAssertions { * @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 3e729e9139c2..154b5cb7f799 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 class FrozenExistenceDeciderIT extends AbstractFrozenAutoscalingIntegTest 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 9a171663e9df..25bd08afcad7 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 class ReactiveStorageIT extends AutoscalingStorageIntegTestCase { 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 class ReactiveStorageIT extends AutoscalingStorageIntegTestCase { 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 class ReactiveStorageIT extends AutoscalingStorageIntegTestCase { 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 e005e2143522..df1b2c9f00f4 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 @@ package org.elasticsearch.xpack.esql.action; 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.List; 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 @@ public class EsqlDisruptionIT extends EsqlActionIT { 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 7b33fe670efd..e378ce06611c 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 @@ package org.elasticsearch.index.engine.frozen; 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 class FrozenIndexIT extends ESIntegTestCase { 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 class FrozenIndexIT extends ESIntegTestCase { 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 cac1bdd096be..46f568d286f9 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.apache.logging.log4j.Logger; 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 class NodeShutdownTasksIT extends ESIntegTestCase { // 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 3787761a2b28..a64df7f871d9 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 class SLMSnapshotBlockingIntegTests extends AbstractSnapshotIntegTestCase // 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 11/34] 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 4f4d6da837a8..03a0df5cc395 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 8b52aa84aef2..3dde3ba75be7 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 @@ public class TimeSeriesSortedSourceOperatorFactory extends LuceneOperator.Factor 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 12/34] [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 | 58 +- .../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 | 1584 ++++++++------- .../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 | 103 +- .../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 | 402 +++- .../rest-api-spec/test/esql/10_basic.yml | 45 +- 31 files changed, 2871 insertions(+), 2142 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 000000000000..1f077a4a2cb7 --- /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 1eb7e1cce5cb..47246a4e190d 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 final class StringUtils { 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 0c5ec5eac716..a672e4a50612 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 abstract class RestEsqlTestCase extends ESRestTestCase { 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( + 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, {\"value\": \"y\"}]")) - ); - assertThat(EntityUtils.toString(re.getResponse().getEntity()), containsString("Required [type]")); - } - - public void testErrorMessageForMissingValueInParams() throws IOException { - ResponseException re = expectThrows( - ResponseException.class, - () -> runEsql(requestObjectBuilder().query("row a = 1").params("[\"x\", 123, true, {\"type\": \"y\"}]")) - ); - 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}]")) + () -> runEsqlSync(requestObjectBuilder().query("row a = ?0, b= ?2").params("[{\"n1\": \"v1\"}]")) ); assertThat( EntityUtils.toString(re.getResponse().getEntity()), - containsString("EVAL does not support type [byte] in expression [?]") + containsString("No parameter is defined for position 0, did you mean position 1") ); + assertThat( + EntityUtils.toString(re.getResponse().getEntity()), + 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 @@ public abstract class RestEsqlTestCase extends ESRestTestCase { 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 fb424b16ac40..61ce9bd9152e 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 30ce0d5eea55..04798fc3dca8 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 29892d464c0e..69d65ea9a214 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 30ce0d5eea55..04798fc3dca8 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 9e8553911268..3eef9f7356b3 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 @@ public class EsqlCapabilities { 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 542b220d398d..e81c9919fe0a 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.CancellableTask; 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 class EsqlQueryRequest extends org.elasticsearch.xpack.core.esql.action.E 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 793f453d5ebf..2c6b5e7a6b49 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 @@ package org.elasticsearch.xpack.esql.action; 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<>(); - static { - PARAM_PARSER.declareField(constructorArg(), (p, c) -> parseFieldsValue(p), VALUE, ObjectParser.ValueType.VALUE); - PARAM_PARSER.declareString(constructorArg(), TYPE); + TempObjects() {} + + 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 @@ final class RequestXContent { (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 @@ final class RequestXContent { return parser; } - private static List 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 406b9e21e1d5..3b39e6a9d1fd 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 6b1b50df32f5..000000000000 --- 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 6f9e20e95430..eb3689d0900d 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 f9ca7ff95c84..1511be73d40e 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 @@ public class EsqlBaseLexer extends Lexer { "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 @@ public class EsqlBaseLexer extends Lexer { "'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 @@ public class EsqlBaseLexer extends Lexer { "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 class EsqlBaseLexer extends Lexer { 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 class EsqlBaseLexer extends Lexer { "\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\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\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\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 class EsqlBaseLexer extends Lexer { "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 76663717c562..590002059011 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 1c136a946a0f..6c21529d6a64 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 @@ public class EsqlBaseParser extends Parser { "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 @@ public class EsqlBaseParser extends Parser { "'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 @@ public class EsqlBaseParser extends Parser { "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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(110); + setState(112); query(0); - setState(111); + setState(113); match(EOF); } } @@ -308,11 +309,11 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { { _localctx = new CompositeQueryContext(new QueryContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_query); - setState(116); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(117); - match(PIPE); setState(118); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); + setState(119); + match(PIPE); + setState(120); processingCommand(); } } } - setState(123); + setState(125); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,0,_ctx); } @@ -393,48 +394,48 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(148); + setState(150); match(WHERE); - setState(149); + setState(151); booleanExpression(0); } } @@ -866,7 +867,7 @@ public class EsqlBaseParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(179); + setState(181); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: @@ -875,9 +876,9 @@ public class EsqlBaseParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(152); + setState(154); match(NOT); - setState(153); + setState(155); booleanExpression(7); } break; @@ -886,7 +887,7 @@ public class EsqlBaseParser extends Parser { _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(154); + setState(156); valueExpression(); } break; @@ -895,7 +896,7 @@ public class EsqlBaseParser extends Parser { _localctx = new RegexExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(155); + setState(157); regexBooleanExpression(); } break; @@ -904,41 +905,41 @@ public class EsqlBaseParser extends Parser { _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); - match(IN); - setState(161); - match(LP); setState(162); + match(IN); + setState(163); + match(LP); + 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 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { 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 @@ public class EsqlBaseParser extends Parser { _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(181); - if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); - setState(182); - ((LogicalBinaryContext)_localctx).operator = match(AND); setState(183); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(184); + ((LogicalBinaryContext)_localctx).operator = match(AND); + setState(185); ((LogicalBinaryContext)_localctx).right = booleanExpression(5); } break; @@ -996,18 +997,18 @@ public class EsqlBaseParser extends Parser { _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(184); - if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(185); - ((LogicalBinaryContext)_localctx).operator = match(OR); setState(186); + if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(187); + ((LogicalBinaryContext)_localctx).operator = match(OR); + 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { _localctx = new ComparisonContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(209); - ((ComparisonContext)_localctx).left = operatorExpression(0); - setState(210); - comparisonOperator(); setState(211); + ((ComparisonContext)_localctx).left = operatorExpression(0); + setState(212); + comparisonOperator(); + setState(213); ((ComparisonContext)_localctx).right = operatorExpression(0); } break; @@ -1333,7 +1334,7 @@ public class EsqlBaseParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(219); + setState(221); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: @@ -1342,7 +1343,7 @@ public class EsqlBaseParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(216); + setState(218); primaryExpression(0); } break; @@ -1351,7 +1352,7 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { 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 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(223); + setState(225); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3); } break; @@ -1406,9 +1407,9 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { _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 @@ public class EsqlBaseParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(240); + setState(242); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) { case 1: @@ -1593,7 +1594,7 @@ public class EsqlBaseParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(233); + setState(235); constant(); } break; @@ -1602,7 +1603,7 @@ public class EsqlBaseParser extends Parser { _localctx = new DereferenceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(234); + setState(236); qualifiedName(); } break; @@ -1611,7 +1612,7 @@ public class EsqlBaseParser extends Parser { _localctx = new FunctionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(235); + setState(237); functionExpression(); } break; @@ -1620,17 +1621,17 @@ public class EsqlBaseParser extends Parser { _localctx = new ParenthesizedExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(236); - match(LP); - setState(237); - booleanExpression(0); setState(238); + match(LP); + setState(239); + booleanExpression(0); + 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 @@ public class EsqlBaseParser extends Parser { { _localctx = new InlineCastContext(new PrimaryExpressionContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_primaryExpression); - setState(242); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(243); - match(CAST_OP); setState(244); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); + setState(245); + match(CAST_OP); + setState(246); dataType(); } } } - setState(249); + setState(251); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); } @@ -1712,16 +1713,16 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { default: break; } - setState(263); + setState(265); match(RP); } } @@ -1825,7 +1827,7 @@ public class EsqlBaseParser extends Parser { _localctx = new ToDataTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(265); + setState(267); identifier(); } } @@ -1872,9 +1874,9 @@ public class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(267); + setState(269); match(ROW); - setState(268); + setState(270); fields(); } } @@ -1928,23 +1930,23 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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); - qualifiedName(); - setState(280); - match(ASSIGN); setState(281); + qualifiedName(); + setState(282); + match(ASSIGN); + setState(283); booleanExpression(0); } break; @@ -2071,34 +2073,34 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(297); + setState(299); match(INDEX_UNQUOTED_IDENTIFIER); } } @@ -2192,20 +2194,20 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(312); - match(OPENING_BRACKET); - setState(313); - metadataOption(); setState(314); + match(OPENING_BRACKET); + setState(315); + metadataOption(); + setState(316); match(CLOSING_BRACKET); } } @@ -2399,46 +2401,46 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(332); + setState(334); match(EVAL); - setState(333); + setState(335); fields(); } } @@ -2543,26 +2545,26 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(375); + setState(377); match(ID_PATTERN); } } @@ -3149,21 +3151,23 @@ public class EsqlBaseParser extends Parser { } } @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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { _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 class EsqlBaseParser extends Parser { _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(381); + setState(383); decimalValue(); } break; @@ -3248,7 +3252,7 @@ public class EsqlBaseParser extends Parser { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(382); + setState(384); integerValue(); } break; @@ -3256,23 +3260,23 @@ public class EsqlBaseParser extends Parser { _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 class EsqlBaseParser extends Parser { _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 class EsqlBaseParser extends Parser { _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 class EsqlBaseParser extends Parser { _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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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); - match(SORT); - setState(425); - orderExpression(); setState(430); + match(SORT); + setState(431); + orderExpression(); + 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { } 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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); - match(RENAME); - setState(448); - renameClause(); setState(453); + match(RENAME); + setState(454); + renameClause(); + 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { } } - setState(494); + setState(500); match(DECIMAL_LITERAL); } } @@ -4322,17 +4417,17 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { } } - setState(499); + setState(505); match(INTEGER_LITERAL); } } @@ -4385,11 +4480,11 @@ public class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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); - match(WITH); - setState(525); - enrichWithClause(); setState(530); + match(WITH); + setState(531); + enrichWithClause(); + 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 class EsqlBaseParser extends Parser { 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 class EsqlBaseParser extends Parser { 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 @@ public class EsqlBaseParser extends Parser { } 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 @@ public class EsqlBaseParser extends Parser { "#\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 760e8f4cb9cd..0da4c187a3d4 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 aee998364f94..ea1c9aca9988 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 0c53191ab9ab..081deb03e835 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 54f506c9d3b3..d1ffbd5fa0b3 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 147d946dcef0..56822386b295 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.logging.Logger; 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 class EsqlParser { private T invokeParser( String query, - List params, + QueryParams params, Function parseFunction, BiFunction result ) { @@ -57,8 +57,8 @@ public class EsqlParser { 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 @@ public class EsqlParser { 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 class EsqlParser { 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 @@ public class EsqlParser { 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 class EsqlParser { 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 a32ae9167aeb..59801e59555b 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.apache.lucene.util.automaton.Operations; 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.time.temporal.TemporalAmount; 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.type.DataType.TIME_DURATION; 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 abstract class ExpressionBuilder extends IdentifierBuilder { @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 { - - 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); - } + QueryParam param = paramByToken(ctx.PARAM()); + return visitParam(ctx, param); } - private TypedParamValue param(TerminalNode node) { + @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); + } + + 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 ec238c1fcf31..f829a7cb6ed0 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 000000000000..022c18fdc586 --- /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 000000000000..ebba6d3d0b48 --- /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 74cc53e51b36..000000000000 --- 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 10116bb24e6b..1f5374b73466 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.LogicalPlanOptimizer; 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 class EsqlSession { ); } - 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 ab0bc114a276..a8ad53b8bc66 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.TaskId; 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 class EsqlQueryRequestTests extends ESTestCase { 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 @@ public class EsqlQueryRequestTests extends ESTestCase { } } - 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 07a364bf9196..e5f59f1ffa8a 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.test.ESTestCase; 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 java.util.List; 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 @@ public class VerifierTests extends ESTestCase { } 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 884b24fc0fc5..28662c2470f1 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.Limit; 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.Lookup; 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.FALSE; 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.hasSize; 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 class StatementParserTests extends ESTestCase { } 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 class StatementParserTests extends ESTestCase { 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 class StatementParserTests extends ESTestCase { 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")); - 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"); - expectError( - "row x = ?", - List.of(new TypedParamValue("date_period", "12 months foo")), - "Cannot parse [12 months foo] to DATE_PERIOD" - ); - expectError( - "row x = ?", - List.of(new TypedParamValue("time_duration", "12 minutes bar")), - "Cannot parse [12 minutes bar] to TIME_DURATION" - ); - 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" - ); + field = row.fields().get(6); + assertThat(field.name(), is("e")); + assertThat(field, instanceOf(Alias.class)); + alias = (Alias) field; + assertThat(alias.child().fold(), is(9)); - expectError( - "row x = ?", - List.of(new TypedParamValue("date_period", "2 minutes")), - "Cannot parse [2 minutes] to DATE_PERIOD, did you mean TIME_DURATION?" - ); - expectError( - "row x = ?", - List.of(new TypedParamValue("time_duration", "11 months")), - "Cannot parse [11 months] to TIME_DURATION, did you mean DATE_PERIOD?" - ); + 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 TypedParamValue("integer", 1)), "Not enough actual parameters 1"); + 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 testInvalidPositionalParams() { + expectError( + "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( + "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( + "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( + "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( + "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 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 @@ public class StatementParserTests extends ESTestCase { } 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 @@ public class StatementParserTests extends ESTestCase { 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 ab0261d91663..1c95e961d053 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 13/34] 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 207794c064da..b7928898a3bb 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 97f4859e012a..d9b08b7281f7 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 14/34] 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 c2be2da12534..e85209c19d82 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -188,6 +188,7 @@ public class TransportVersions { 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 ebf01feaaa89..51699c1f7dcd 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 @@ package org.elasticsearch.action.admin.cluster.node.info; 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 final class NodesInfoRequest extends BaseNodesRequest { 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 c441c6daf89b..ff88bc5fcf46 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.action.support.nodes.BaseNodesRequest; 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 class NodesStatsRequest extends BaseNodesRequest { 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 class NodesStatsRequest extends BaseNodesRequest { 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 ca2ec4e5607e..bba669e07a70 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 @@ package org.elasticsearch.action.admin.cluster.stats; 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 @@ import java.util.Map; */ 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 class ClusterStatsRequest extends BaseNodesRequest { 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 f1b6faaca439..2a8fecde7ee9 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.io.stream.StreamOutput; 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 @@ public class TransportClusterStatsAction extends TransportNodesAction< @Override protected ClusterStatsNodeRequest newNodeRequest(ClusterStatsRequest request) { - return new ClusterStatsNodeRequest(request); + return new ClusterStatsNodeRequest(); } @Override @@ -251,18 +253,16 @@ public class TransportClusterStatsAction extends TransportNodesAction< ); } + @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 class TransportClusterStatsAction extends TransportNodesAction< @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 22953f9959c1..9883eec6896c 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 class CancellableTasksTests extends TaskManagerTestCase { } 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 @@ public class CancellableTasksTests extends TaskManagerTestCase { boolean shouldBlock, CountDownLatch actionStartedLatch ) { - super(actionName, threadPool, clusterService, transportService, CancellableNodesRequest::new, CancellableNodeRequest::new); + super(actionName, threadPool, clusterService, transportService, CancellableNodeRequest::new); this.shouldBlock = shouldBlock; this.actionStartedLatch = actionStartedLatch; } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TaskManagerTestCase.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TaskManagerTestCase.java index f943ff14002c..f3450bbff669 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TaskManagerTestCase.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TaskManagerTestCase.java @@ -144,7 +144,6 @@ public abstract class TaskManagerTestCase extends ESTestCase { ThreadPool threadPool, ClusterService clusterService, TransportService transportService, - Writeable.Reader 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 63629e16974d..6f345eb7dcda 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 class TestTaskPlugin extends Plugin implements ActionPlugin, NetworkPlugi } 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 6f4da1fe1ebe..969ed50685bc 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 class TransportTasksActionTests extends TaskManagerTestCase { 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 class TransportTasksActionTests extends TaskManagerTestCase { 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 689040f9b6c5..d0535665d368 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 class TransportNodesActionTests extends ESTestCase { 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 @@ public class TransportNodesActionTests extends ESTestCase { 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 @@ public class TransportNodesActionTests extends ESTestCase { } 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 29edc88ecda7..00dcd5642401 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 class GetInferenceDiagnosticsAction extends ActionType { + + @UpdateForV9 // this constructor is unused in v9 public NodesDeprecationCheckRequest(StreamInput in) throws IOException { super(in); } @@ -24,6 +27,7 @@ public class NodesDeprecationCheckRequest extends BaseNodesRequest Date: Tue, 11 Jun 2024 17:34:16 +0100 Subject: [PATCH 15/34] 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 8a2e7684cadf..626cdb8046f5 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. From dbf388cec745665df9e8b3a80914d452e786f079 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 11 Jun 2024 18:06:43 +0100 Subject: [PATCH 16/34] Fix trappy reroute timeout (#109587) Relates #107984 --- .../admin/indices/create/ShrinkIndexIT.java | 5 +++- .../cluster/allocation/ClusterRerouteIT.java | 27 +++++++++++++------ .../cluster/routing/PrimaryAllocationIT.java | 2 +- .../elasticsearch/recovery/RelocationIT.java | 2 +- .../reroute/ClusterRerouteRequest.java | 5 ++-- .../reroute/ClusterRerouteRequestBuilder.java | 11 +++++++- .../cluster/RestClusterRerouteAction.java | 4 +-- .../reroute/ClusterRerouteRequestTests.java | 15 ++++++----- .../cluster/reroute/ClusterRerouteTests.java | 6 ++--- .../AbstractClientHeadersTestCase.java | 2 +- .../metadata/AutoExpandReplicasTests.java | 2 +- .../allocation/FailedNodeRoutingTests.java | 3 ++- ...ClusterStateServiceRandomUpdatesTests.java | 2 +- .../snapshots/SnapshotResiliencyTests.java | 2 +- .../cluster/reroute/ClusterRerouteUtils.java | 6 +++-- 15 files changed, 60 insertions(+), 34 deletions(-) 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 6b2c7f0a9580..3712ad8c35f6 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 @@ -398,7 +398,10 @@ public class ShrinkIndexIT extends ESIntegTestCase { refreshClusterInfo(); // kick off a retry and wait until it's done! final var clusterRerouteResponse = safeGet( - client().execute(TransportClusterRerouteAction.TYPE, new ClusterRerouteRequest().setRetryFailed(true)) + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).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 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 5f75b62cabb6..7c13171ea76a 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/allocation/ClusterRerouteIT.java @@ -104,7 +104,7 @@ public class ClusterRerouteIT extends ESIntegTestCase { state = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) .dryRun(true) ) @@ -123,7 +123,8 @@ public class ClusterRerouteIT extends ESIntegTestCase { state = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) + .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) ) ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); @@ -151,7 +152,8 @@ public class ClusterRerouteIT extends ESIntegTestCase { state = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()).add(new MoveAllocationCommand("test", 0, node_1, node_2)) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) + .add(new MoveAllocationCommand("test", 0, node_1, node_2)) ) ).getState(); @@ -259,7 +261,8 @@ public class ClusterRerouteIT extends ESIntegTestCase { state = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) + .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) ) ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); @@ -311,7 +314,8 @@ public class ClusterRerouteIT extends ESIntegTestCase { state = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()).add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) + .add(new AllocateEmptyPrimaryAllocationCommand("test", 0, node_1, true)) ) ).getState(); assertThat(state.getRoutingNodes().unassigned().size(), equalTo(1)); @@ -359,7 +363,10 @@ public class ClusterRerouteIT extends ESIntegTestCase { logger.info("--> try to move the shard from node1 to node2"); MoveAllocationCommand cmd = new MoveAllocationCommand("test", 0, node_1, node_2); ClusterRerouteResponse resp = safeGet( - client().execute(TransportClusterRerouteAction.TYPE, new ClusterRerouteRequest().add(cmd).explain(true)) + client().execute( + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).add(cmd).explain(true) + ) ); RoutingExplanations e = resp.getExplanations(); assertThat(e.explanations().size(), equalTo(1)); @@ -411,7 +418,9 @@ public class ClusterRerouteIT extends ESIntegTestCase { ClusterRerouteResponse dryRunResponse = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(randomBoolean()).dryRun(true).add(dryRunAllocation) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).explain(randomBoolean()) + .dryRun(true) + .add(dryRunAllocation) ) ); @@ -445,7 +454,9 @@ public class ClusterRerouteIT extends ESIntegTestCase { ClusterRerouteResponse response = safeGet( client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().explain(true) // so we get a NO decision back rather than an exception + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT) + // set explain(true) so we get a NO decision back rather than an exception + .explain(true) .add(yesDecisionAllocation) .add(noDecisionAllocation) ) 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 db84f2a0a34d..d97063454920 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java @@ -260,7 +260,7 @@ public class PrimaryAllocationIT extends ESIntegTestCase { TransportIndicesShardStoresAction.TYPE, new IndicesShardStoresRequest(idxName) ).get().getStoreStatuses().get(idxName); - final var rerouteRequest = new ClusterRerouteRequest(); + final var rerouteRequest = new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT); for (Map.Entry> shardStoreStatuses : storeStatuses.entrySet()) { int shardId = shardStoreStatuses.getKey(); IndicesShardStoresResponse.StoreStatus storeStatus = randomFrom(shardStoreStatuses.getValue()); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java index f0026dfa0a34..17daf403e056 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/recovery/RelocationIT.java @@ -611,7 +611,7 @@ public class RelocationIT extends ESIntegTestCase { logger.info("--> relocate the shard from node1 to node2"); ActionFuture relocationListener = client().execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().add(new MoveAllocationCommand("test", 0, node1, node2)) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).add(new MoveAllocationCommand("test", 0, node1, node2)) ); logger.info("--> index 100 docs while relocating"); for (int i = 20; i < 120; i++) { diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java index 402f3666c2e8..b245a752524e 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java @@ -13,6 +13,7 @@ import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand; import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.TimeValue; import java.io.IOException; import java.util.Objects; @@ -34,8 +35,8 @@ public class ClusterRerouteRequest extends AcknowledgedRequest { public ClusterRerouteRequestBuilder(ElasticsearchClient client) { - super(client, TransportClusterRerouteAction.TYPE, new ClusterRerouteRequest()); + super( + client, + TransportClusterRerouteAction.TYPE, + new ClusterRerouteRequest( + MasterNodeRequest.TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT, + AcknowledgedRequest.DEFAULT_ACK_TIMEOUT + ) + ); } /** 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 47d6198114fc..efd6f3e7b62c 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 @@ -100,12 +100,10 @@ public class RestClusterRerouteAction extends BaseRestHandler { } public static ClusterRerouteRequest createRequest(RestRequest request) throws IOException { - ClusterRerouteRequest clusterRerouteRequest = new ClusterRerouteRequest(); + final var clusterRerouteRequest = new ClusterRerouteRequest(getMasterNodeTimeout(request), getAckTimeout(request)); clusterRerouteRequest.dryRun(request.paramAsBoolean("dry_run", clusterRerouteRequest.dryRun())); clusterRerouteRequest.explain(request.paramAsBoolean("explain", clusterRerouteRequest.explain())); - clusterRerouteRequest.ackTimeout(getAckTimeout(request)); clusterRerouteRequest.setRetryFailed(request.paramAsBoolean("retry_failed", clusterRerouteRequest.isRetryFailed())); - clusterRerouteRequest.masterNodeTimeout(getMasterNodeTimeout(request)); request.applyContentParser(parser -> PARSER.parse(parser, clusterRerouteRequest, null)); return clusterRerouteRequest; } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java index 7ccdb5da6d73..5c39275abbcf 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java @@ -21,8 +21,8 @@ import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.network.NetworkModule; -import org.elasticsearch.core.TimeValue; import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestUtils; import org.elasticsearch.rest.action.admin.cluster.RestClusterRerouteAction; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; @@ -38,6 +38,7 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; +import static org.elasticsearch.action.support.master.AcknowledgedRequest.DEFAULT_ACK_TIMEOUT; import static org.elasticsearch.core.TimeValue.timeValueMillis; import static org.elasticsearch.rest.RestUtils.REST_MASTER_TIMEOUT_PARAM; @@ -80,7 +81,7 @@ public class ClusterRerouteRequestTests extends ESTestCase { } private ClusterRerouteRequest randomRequest() { - ClusterRerouteRequest request = new ClusterRerouteRequest(); + ClusterRerouteRequest request = new ClusterRerouteRequest(randomTimeValue(), randomTimeValue()); int commands = between(0, 10); for (int i = 0; i < commands; i++) { request.add(randomFrom(RANDOM_COMMAND_GENERATORS).get()); @@ -97,7 +98,7 @@ public class ClusterRerouteRequestTests extends ESTestCase { assertEquals(request, request); assertEquals(request.hashCode(), request.hashCode()); - ClusterRerouteRequest copy = new ClusterRerouteRequest().add( + ClusterRerouteRequest copy = new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).add( request.getCommands().commands().toArray(new AllocationCommand[0]) ); AcknowledgedRequest clusterRerouteRequestAcknowledgedRequest = copy.dryRun(request.dryRun()) @@ -196,14 +197,14 @@ public class ClusterRerouteRequestTests extends ESTestCase { builder.field("dry_run", original.dryRun()); } params.put("explain", Boolean.toString(original.explain())); - if (false == original.ackTimeout().equals(AcknowledgedRequest.DEFAULT_ACK_TIMEOUT) || randomBoolean()) { - params.put("timeout", original.ackTimeout().toString()); + if (false == original.ackTimeout().equals(DEFAULT_ACK_TIMEOUT) || randomBoolean()) { + params.put("timeout", original.ackTimeout().getStringRep()); } if (original.isRetryFailed() || randomBoolean()) { params.put("retry_failed", Boolean.toString(original.isRetryFailed())); } - if (false == original.masterNodeTimeout().equals(TimeValue.THIRTY_SECONDS) || randomBoolean()) { - params.put(REST_MASTER_TIMEOUT_PARAM, original.masterNodeTimeout().toString()); + if (false == original.masterNodeTimeout().equals(RestUtils.REST_MASTER_TIMEOUT_DEFAULT) || randomBoolean()) { + params.put(REST_MASTER_TIMEOUT_PARAM, original.masterNodeTimeout().getStringRep()); } if (original.getCommands() != null) { hasBody = true; diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java index 19c268100d4a..d2eb8d958bf8 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java @@ -51,7 +51,7 @@ import static org.hamcrest.Matchers.not; public class ClusterRerouteTests extends ESAllocationTestCase { public void testSerializeRequest() throws IOException { - ClusterRerouteRequest req = new ClusterRerouteRequest(); + ClusterRerouteRequest req = new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT); req.setRetryFailed(randomBoolean()); req.dryRun(randomBoolean()); req.explain(randomBoolean()); @@ -86,7 +86,7 @@ public class ClusterRerouteTests extends ESAllocationTestCase { var responseRef = new AtomicReference(); var responseActionListener = ActionTestUtils.assertNoFailureListener(responseRef::set); - var request = new ClusterRerouteRequest().dryRun(true); + var request = new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).dryRun(true); var task = new TransportClusterRerouteAction.ClusterRerouteResponseAckedClusterStateUpdateTask( logger, allocationService, @@ -112,7 +112,7 @@ public class ClusterRerouteTests extends ESAllocationTestCase { ); ClusterState clusterState = createInitialClusterState(allocationService); - var req = new ClusterRerouteRequest().dryRun(false); + var req = new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).dryRun(false); var task = new TransportClusterRerouteAction.ClusterRerouteResponseAckedClusterStateUpdateTask( logger, allocationService, 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 2ed69810c890..652e7f014b8e 100644 --- a/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java +++ b/server/src/test/java/org/elasticsearch/client/internal/AbstractClientHeadersTestCase.java @@ -121,7 +121,7 @@ public abstract class AbstractClientHeadersTestCase extends ESTestCase { .execute(new AssertingActionListener<>(TransportCreateSnapshotAction.TYPE.name(), client.threadPool())); client.execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest(), + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT), new AssertingActionListener<>(TransportClusterRerouteAction.TYPE.name(), client.threadPool()) ); diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/AutoExpandReplicasTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/AutoExpandReplicasTests.java index 1ca7333c90a2..8a13d0cdc14f 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/AutoExpandReplicasTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/AutoExpandReplicasTests.java @@ -142,7 +142,7 @@ public class AutoExpandReplicasTests extends ESTestCase { state, state.routingTable().index("index").shard(0).shardsWithState(ShardRoutingState.INITIALIZING) ); - state = cluster.reroute(state, new ClusterRerouteRequest()); + state = cluster.reroute(state, new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT)); } IndexShardRoutingTable preTable = state.routingTable().index("index").shard(0); diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java index d76e9912cef0..608c81417531 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/FailedNodeRoutingTests.java @@ -123,7 +123,8 @@ public class FailedNodeRoutingTests extends ESAllocationTestCase { for (int i = 0; i < randomIntBetween(4, 8); i++) { DiscoveryNodes newNodes = DiscoveryNodes.builder(state.nodes()).add(createNode()).build(); state = ClusterState.builder(state).nodes(newNodes).build(); - state = cluster.reroute(state, new ClusterRerouteRequest()); // always reroute after adding node + // always reroute after adding node + state = cluster.reroute(state, new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT)); } // Log the node versions (for debugging if necessary) diff --git a/server/src/test/java/org/elasticsearch/indices/cluster/IndicesClusterStateServiceRandomUpdatesTests.java b/server/src/test/java/org/elasticsearch/indices/cluster/IndicesClusterStateServiceRandomUpdatesTests.java index 1ace9a786cca..0ebcbff6bf86 100644 --- a/server/src/test/java/org/elasticsearch/indices/cluster/IndicesClusterStateServiceRandomUpdatesTests.java +++ b/server/src/test/java/org/elasticsearch/indices/cluster/IndicesClusterStateServiceRandomUpdatesTests.java @@ -441,7 +441,7 @@ public class IndicesClusterStateServiceRandomUpdatesTests extends AbstractIndice // randomly reroute if (rarely()) { - state = cluster.reroute(state, new ClusterRerouteRequest()); + state = cluster.reroute(state, new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT)); } // randomly start and fail allocated shards diff --git a/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java b/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java index 8a5d282fe014..cbdb30652f96 100644 --- a/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java +++ b/server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java @@ -1052,7 +1052,7 @@ public class SnapshotResiliencyTests extends ESTestCase { scheduleNow( () -> testClusterNodes.randomMasterNodeSafe().client.execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().add( + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).add( new AllocateEmptyPrimaryAllocationCommand( index, shardRouting.shardId().id(), 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 index 3da245ec430a..5bfff80e3b86 100644 --- 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 @@ -14,6 +14,7 @@ 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.TEST_REQUEST_TIMEOUT; import static org.elasticsearch.test.ESTestCase.asInstanceOf; import static org.elasticsearch.test.ESTestCase.safeAwait; import static org.elasticsearch.test.ESTestCase.safeGet; @@ -45,7 +46,8 @@ public class ClusterRerouteUtils { safeGet( client.execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().setRetryFailed(retryFailed).add(allocationCommands) + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).setRetryFailed(retryFailed) + .add(allocationCommands) ) ) ); @@ -60,7 +62,7 @@ public class ClusterRerouteUtils { SubscribableListener.newForked( l -> client.execute( TransportClusterRerouteAction.TYPE, - new ClusterRerouteRequest().add(allocationCommands), + new ClusterRerouteRequest(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).add(allocationCommands), ActionTestUtils.assertNoSuccessListener(l::onResponse) ) ) From 53aefdd79d0a4c3d8d913a9c0472d316866f793f Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 11 Jun 2024 15:04:38 -0400 Subject: [PATCH 17/34] add hexstring support byte painless scorers (#109492) Hexidecimal strings are supported for index input and for kNN queries. We should support them for byte vectors in painless. This commit addresses this for our common scoring functions. closes: #109412 --- docs/changelog/109492.yaml | 5 + .../index.asciidoc | 8 +- .../whitelist-json/painless-score.json | 2 +- .../org.elasticsearch.script.score.txt | 8 +- .../painless/145_dense_vector_byte_basic.yml | 61 ++++++++++ .../painless/155_dense_vector_byte_l1l2.yml | 61 ++++++++++ .../script/VectorScoreScriptUtils.java | 114 ++++++++++++++++-- .../script/VectorScoreScriptUtilsTests.java | 17 ++- 8 files changed, 253 insertions(+), 23 deletions(-) create mode 100644 docs/changelog/109492.yaml diff --git a/docs/changelog/109492.yaml b/docs/changelog/109492.yaml new file mode 100644 index 000000000000..d4d1e83eb778 --- /dev/null +++ b/docs/changelog/109492.yaml @@ -0,0 +1,5 @@ +pr: 109492 +summary: Add hexstring support byte painless scorers +area: Search +type: bug +issues: [] diff --git a/docs/painless/painless-api-reference/painless-api-reference-score/index.asciidoc b/docs/painless/painless-api-reference/painless-api-reference-score/index.asciidoc index e91b8026dc33..775c0cc21242 100644 --- a/docs/painless/painless-api-reference/painless-api-reference-score/index.asciidoc +++ b/docs/painless/painless-api-reference/painless-api-reference-score/index.asciidoc @@ -10,7 +10,7 @@ The following specialized API is available in the Score context. ==== Static Methods The following methods are directly callable without a class/instance qualifier. Note parameters denoted by a (*) are treated as read-only values. -* double cosineSimilarity(List *, String *) +* double cosineSimilarity(Object *, String *) * double decayDateExp(String *, String *, String *, double *, ZonedDateTime) * double decayDateGauss(String *, String *, String *, double *, ZonedDateTime) * double decayDateLinear(String *, String *, String *, double *, ZonedDateTime) @@ -20,9 +20,9 @@ The following methods are directly callable without a class/instance qualifier. * double decayNumericExp(double *, double *, double *, double *, double) * double decayNumericGauss(double *, double *, double *, double *, double) * double decayNumericLinear(double *, double *, double *, double *, double) -* double dotProduct(List *, String *) -* double l1norm(List *, String *) -* double l2norm(List *, String *) +* double dotProduct(Object *, String *) +* double l1norm(Object *, String *) +* double l2norm(Object *, String *) * double randomScore(int *) * double randomScore(int *, String *) * double saturation(double, double) diff --git a/modules/lang-painless/src/main/generated/whitelist-json/painless-score.json b/modules/lang-painless/src/main/generated/whitelist-json/painless-score.json index 56fe66d849b8..da9f7f7b6038 100644 --- a/modules/lang-painless/src/main/generated/whitelist-json/painless-score.json +++ b/modules/lang-painless/src/main/generated/whitelist-json/painless-score.json @@ -1 +1 @@ -{"name":"score","classes":[{"name":"String","imported":true,"constructors":[{"declaring":"String","parameters":[]}],"static_methods":[{"declaring":"String","name":"copyValueOf","return":"String","parameters":["char[]"]},{"declaring":"String","name":"copyValueOf","return":"String","parameters":["char[]","int","int"]},{"declaring":"String","name":"format","return":"String","parameters":["String","def[]"]},{"declaring":"String","name":"format","return":"String","parameters":["Locale","String","def[]"]},{"declaring":"String","name":"join","return":"String","parameters":["CharSequence","Iterable"]},{"declaring":"String","name":"valueOf","return":"String","parameters":["def"]}],"methods":[{"declaring":"CharSequence","name":"charAt","return":"char","parameters":["int"]},{"declaring":"CharSequence","name":"chars","return":"IntStream","parameters":[]},{"declaring":"String","name":"codePointAt","return":"int","parameters":["int"]},{"declaring":"String","name":"codePointBefore","return":"int","parameters":["int"]},{"declaring":"String","name":"codePointCount","return":"int","parameters":["int","int"]},{"declaring":"CharSequence","name":"codePoints","return":"IntStream","parameters":[]},{"declaring":"String","name":"compareTo","return":"int","parameters":["String"]},{"declaring":"String","name":"compareToIgnoreCase","return":"int","parameters":["String"]},{"declaring":"String","name":"concat","return":"String","parameters":["String"]},{"declaring":"String","name":"contains","return":"boolean","parameters":["CharSequence"]},{"declaring":"String","name":"contentEquals","return":"boolean","parameters":["CharSequence"]},{"declaring":null,"name":"decodeBase64","return":"String","parameters":[]},{"declaring":null,"name":"encodeBase64","return":"String","parameters":[]},{"declaring":"String","name":"endsWith","return":"boolean","parameters":["String"]},{"declaring":"Object","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":"String","name":"equalsIgnoreCase","return":"boolean","parameters":["String"]},{"declaring":"String","name":"getChars","return":"void","parameters":["int","int","char[]","int"]},{"declaring":"Object","name":"hashCode","return":"int","parameters":[]},{"declaring":"String","name":"indexOf","return":"int","parameters":["String"]},{"declaring":"String","name":"indexOf","return":"int","parameters":["String","int"]},{"declaring":"String","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"String","name":"lastIndexOf","return":"int","parameters":["String"]},{"declaring":"String","name":"lastIndexOf","return":"int","parameters":["String","int"]},{"declaring":"CharSequence","name":"length","return":"int","parameters":[]},{"declaring":"String","name":"offsetByCodePoints","return":"int","parameters":["int","int"]},{"declaring":"String","name":"regionMatches","return":"boolean","parameters":["int","String","int","int"]},{"declaring":"String","name":"regionMatches","return":"boolean","parameters":["boolean","int","String","int","int"]},{"declaring":"String","name":"replace","return":"String","parameters":["CharSequence","CharSequence"]},{"declaring":null,"name":"replaceAll","return":"String","parameters":["Pattern","Function"]},{"declaring":null,"name":"replaceFirst","return":"String","parameters":["Pattern","Function"]},{"declaring":null,"name":"splitOnToken","return":"String[]","parameters":["String"]},{"declaring":null,"name":"splitOnToken","return":"String[]","parameters":["String","int"]},{"declaring":"String","name":"startsWith","return":"boolean","parameters":["String"]},{"declaring":"String","name":"startsWith","return":"boolean","parameters":["String","int"]},{"declaring":"CharSequence","name":"subSequence","return":"CharSequence","parameters":["int","int"]},{"declaring":"String","name":"substring","return":"String","parameters":["int"]},{"declaring":"String","name":"substring","return":"String","parameters":["int","int"]},{"declaring":"String","name":"toCharArray","return":"char[]","parameters":[]},{"declaring":"String","name":"toLowerCase","return":"String","parameters":[]},{"declaring":"String","name":"toLowerCase","return":"String","parameters":["Locale"]},{"declaring":"CharSequence","name":"toString","return":"String","parameters":[]},{"declaring":"String","name":"toUpperCase","return":"String","parameters":[]},{"declaring":"String","name":"toUpperCase","return":"String","parameters":["Locale"]},{"declaring":"String","name":"trim","return":"String","parameters":[]}],"static_fields":[],"fields":[]},{"name":"DenseVectorScriptDocValues","imported":true,"constructors":[],"static_methods":[],"methods":[{"declaring":"Collection","name":"add","return":"boolean","parameters":["def"]},{"declaring":"List","name":"add","return":"void","parameters":["int","def"]},{"declaring":"Collection","name":"addAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"addAll","return":"boolean","parameters":["int","Collection"]},{"declaring":null,"name":"any","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"asCollection","return":"Collection","parameters":[]},{"declaring":null,"name":"asList","return":"List","parameters":[]},{"declaring":"Collection","name":"clear","return":"void","parameters":[]},{"declaring":null,"name":"collect","return":"List","parameters":["Function"]},{"declaring":null,"name":"collect","return":"def","parameters":["Collection","Function"]},{"declaring":"Collection","name":"contains","return":"boolean","parameters":["def"]},{"declaring":"Collection","name":"containsAll","return":"boolean","parameters":["Collection"]},{"declaring":null,"name":"each","return":"def","parameters":["Consumer"]},{"declaring":null,"name":"eachWithIndex","return":"def","parameters":["ObjIntConsumer"]},{"declaring":"List","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":null,"name":"every","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"find","return":"def","parameters":["Predicate"]},{"declaring":null,"name":"findAll","return":"List","parameters":["Predicate"]},{"declaring":null,"name":"findResult","return":"def","parameters":["Function"]},{"declaring":null,"name":"findResult","return":"def","parameters":["def","Function"]},{"declaring":null,"name":"findResults","return":"List","parameters":["Function"]},{"declaring":"Iterable","name":"forEach","return":"void","parameters":["Consumer"]},{"declaring":"List","name":"get","return":"def","parameters":["int"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String","Object"]},{"declaring":null,"name":"getLength","return":"int","parameters":[]},{"declaring":null,"name":"groupBy","return":"Map","parameters":["Function"]},{"declaring":"List","name":"hashCode","return":"int","parameters":[]},{"declaring":"List","name":"indexOf","return":"int","parameters":["def"]},{"declaring":"Collection","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"Iterable","name":"iterator","return":"Iterator","parameters":[]},{"declaring":null,"name":"join","return":"String","parameters":["String"]},{"declaring":"List","name":"lastIndexOf","return":"int","parameters":["def"]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":[]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":["int"]},{"declaring":"List","name":"remove","return":"def","parameters":["int"]},{"declaring":"Collection","name":"removeAll","return":"boolean","parameters":["Collection"]},{"declaring":"Collection","name":"removeIf","return":"boolean","parameters":["Predicate"]},{"declaring":"List","name":"replaceAll","return":"void","parameters":["UnaryOperator"]},{"declaring":"Collection","name":"retainAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"set","return":"def","parameters":["int","def"]},{"declaring":"Collection","name":"size","return":"int","parameters":[]},{"declaring":"List","name":"sort","return":"void","parameters":["Comparator"]},{"declaring":null,"name":"split","return":"List","parameters":["Predicate"]},{"declaring":"Collection","name":"spliterator","return":"Spliterator","parameters":[]},{"declaring":"Collection","name":"stream","return":"Stream","parameters":[]},{"declaring":"List","name":"subList","return":"List","parameters":["int","int"]},{"declaring":null,"name":"sum","return":"double","parameters":[]},{"declaring":null,"name":"sum","return":"double","parameters":["ToDoubleFunction"]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":[]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":["def[]"]},{"declaring":"Object","name":"toString","return":"String","parameters":[]}],"static_fields":[],"fields":[]},{"name":"VersionScriptDocValues","imported":true,"constructors":[],"static_methods":[],"methods":[{"declaring":"Collection","name":"add","return":"boolean","parameters":["def"]},{"declaring":"List","name":"add","return":"void","parameters":["int","def"]},{"declaring":"Collection","name":"addAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"addAll","return":"boolean","parameters":["int","Collection"]},{"declaring":null,"name":"any","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"asCollection","return":"Collection","parameters":[]},{"declaring":null,"name":"asList","return":"List","parameters":[]},{"declaring":"Collection","name":"clear","return":"void","parameters":[]},{"declaring":null,"name":"collect","return":"List","parameters":["Function"]},{"declaring":null,"name":"collect","return":"def","parameters":["Collection","Function"]},{"declaring":"Collection","name":"contains","return":"boolean","parameters":["def"]},{"declaring":"Collection","name":"containsAll","return":"boolean","parameters":["Collection"]},{"declaring":null,"name":"each","return":"def","parameters":["Consumer"]},{"declaring":null,"name":"eachWithIndex","return":"def","parameters":["ObjIntConsumer"]},{"declaring":"List","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":null,"name":"every","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"find","return":"def","parameters":["Predicate"]},{"declaring":null,"name":"findAll","return":"List","parameters":["Predicate"]},{"declaring":null,"name":"findResult","return":"def","parameters":["Function"]},{"declaring":null,"name":"findResult","return":"def","parameters":["def","Function"]},{"declaring":null,"name":"findResults","return":"List","parameters":["Function"]},{"declaring":"Iterable","name":"forEach","return":"void","parameters":["Consumer"]},{"declaring":"VersionScriptDocValues","name":"get","return":"String","parameters":["int"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String","Object"]},{"declaring":null,"name":"getLength","return":"int","parameters":[]},{"declaring":"VersionScriptDocValues","name":"getValue","return":"String","parameters":[]},{"declaring":null,"name":"groupBy","return":"Map","parameters":["Function"]},{"declaring":"List","name":"hashCode","return":"int","parameters":[]},{"declaring":"List","name":"indexOf","return":"int","parameters":["def"]},{"declaring":"Collection","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"Iterable","name":"iterator","return":"Iterator","parameters":[]},{"declaring":null,"name":"join","return":"String","parameters":["String"]},{"declaring":"List","name":"lastIndexOf","return":"int","parameters":["def"]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":[]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":["int"]},{"declaring":"List","name":"remove","return":"def","parameters":["int"]},{"declaring":"Collection","name":"removeAll","return":"boolean","parameters":["Collection"]},{"declaring":"Collection","name":"removeIf","return":"boolean","parameters":["Predicate"]},{"declaring":"List","name":"replaceAll","return":"void","parameters":["UnaryOperator"]},{"declaring":"Collection","name":"retainAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"set","return":"def","parameters":["int","def"]},{"declaring":"Collection","name":"size","return":"int","parameters":[]},{"declaring":"List","name":"sort","return":"void","parameters":["Comparator"]},{"declaring":null,"name":"split","return":"List","parameters":["Predicate"]},{"declaring":"Collection","name":"spliterator","return":"Spliterator","parameters":[]},{"declaring":"Collection","name":"stream","return":"Stream","parameters":[]},{"declaring":"List","name":"subList","return":"List","parameters":["int","int"]},{"declaring":null,"name":"sum","return":"double","parameters":[]},{"declaring":null,"name":"sum","return":"double","parameters":["ToDoubleFunction"]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":[]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":["def[]"]},{"declaring":"Object","name":"toString","return":"String","parameters":[]}],"static_fields":[],"fields":[]}],"imported_methods":[{"declaring":null,"name":"saturation","return":"double","parameters":["double","double"]},{"declaring":null,"name":"sigmoid","return":"double","parameters":["double","double","double"]}],"class_bindings":[{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$CosineSimilarity","name":"cosineSimilarity","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.util.List","java.lang.String"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateExp","name":"decayDateExp","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateGauss","name":"decayDateGauss","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateLinear","name":"decayDateLinear","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoExp","name":"decayGeoExp","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoGauss","name":"decayGeoGauss","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoLinear","name":"decayGeoLinear","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericExp","name":"decayNumericExp","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericGauss","name":"decayNumericGauss","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericLinear","name":"decayNumericLinear","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$DotProduct","name":"dotProduct","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.util.List","java.lang.String"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$L1Norm","name":"l1norm","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.util.List","java.lang.String"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$L2Norm","name":"l2norm","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.util.List","java.lang.String"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$RandomScoreDoc","name":"randomScore","return":"double","read_only":2,"parameters":["org.elasticsearch.script.ScoreScript","int"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$RandomScoreField","name":"randomScore","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","int","java.lang.String"]}],"instance_bindings":[]} +{"name":"score","classes":[{"name":"String","imported":true,"constructors":[{"declaring":"String","parameters":[]}],"static_methods":[{"declaring":"String","name":"copyValueOf","return":"String","parameters":["char[]"]},{"declaring":"String","name":"copyValueOf","return":"String","parameters":["char[]","int","int"]},{"declaring":"String","name":"format","return":"String","parameters":["String","def[]"]},{"declaring":"String","name":"format","return":"String","parameters":["Locale","String","def[]"]},{"declaring":"String","name":"join","return":"String","parameters":["CharSequence","Iterable"]},{"declaring":"String","name":"valueOf","return":"String","parameters":["def"]}],"methods":[{"declaring":"CharSequence","name":"charAt","return":"char","parameters":["int"]},{"declaring":"CharSequence","name":"chars","return":"IntStream","parameters":[]},{"declaring":"String","name":"codePointAt","return":"int","parameters":["int"]},{"declaring":"String","name":"codePointBefore","return":"int","parameters":["int"]},{"declaring":"String","name":"codePointCount","return":"int","parameters":["int","int"]},{"declaring":"CharSequence","name":"codePoints","return":"IntStream","parameters":[]},{"declaring":"String","name":"compareTo","return":"int","parameters":["String"]},{"declaring":"String","name":"compareToIgnoreCase","return":"int","parameters":["String"]},{"declaring":"String","name":"concat","return":"String","parameters":["String"]},{"declaring":"String","name":"contains","return":"boolean","parameters":["CharSequence"]},{"declaring":"String","name":"contentEquals","return":"boolean","parameters":["CharSequence"]},{"declaring":null,"name":"decodeBase64","return":"String","parameters":[]},{"declaring":null,"name":"encodeBase64","return":"String","parameters":[]},{"declaring":"String","name":"endsWith","return":"boolean","parameters":["String"]},{"declaring":"Object","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":"String","name":"equalsIgnoreCase","return":"boolean","parameters":["String"]},{"declaring":"String","name":"getChars","return":"void","parameters":["int","int","char[]","int"]},{"declaring":"Object","name":"hashCode","return":"int","parameters":[]},{"declaring":"String","name":"indexOf","return":"int","parameters":["String"]},{"declaring":"String","name":"indexOf","return":"int","parameters":["String","int"]},{"declaring":"String","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"String","name":"lastIndexOf","return":"int","parameters":["String"]},{"declaring":"String","name":"lastIndexOf","return":"int","parameters":["String","int"]},{"declaring":"CharSequence","name":"length","return":"int","parameters":[]},{"declaring":"String","name":"offsetByCodePoints","return":"int","parameters":["int","int"]},{"declaring":"String","name":"regionMatches","return":"boolean","parameters":["int","String","int","int"]},{"declaring":"String","name":"regionMatches","return":"boolean","parameters":["boolean","int","String","int","int"]},{"declaring":"String","name":"replace","return":"String","parameters":["CharSequence","CharSequence"]},{"declaring":null,"name":"replaceAll","return":"String","parameters":["Pattern","Function"]},{"declaring":null,"name":"replaceFirst","return":"String","parameters":["Pattern","Function"]},{"declaring":null,"name":"splitOnToken","return":"String[]","parameters":["String"]},{"declaring":null,"name":"splitOnToken","return":"String[]","parameters":["String","int"]},{"declaring":"String","name":"startsWith","return":"boolean","parameters":["String"]},{"declaring":"String","name":"startsWith","return":"boolean","parameters":["String","int"]},{"declaring":"CharSequence","name":"subSequence","return":"CharSequence","parameters":["int","int"]},{"declaring":"String","name":"substring","return":"String","parameters":["int"]},{"declaring":"String","name":"substring","return":"String","parameters":["int","int"]},{"declaring":"String","name":"toCharArray","return":"char[]","parameters":[]},{"declaring":"String","name":"toLowerCase","return":"String","parameters":[]},{"declaring":"String","name":"toLowerCase","return":"String","parameters":["Locale"]},{"declaring":"CharSequence","name":"toString","return":"String","parameters":[]},{"declaring":"String","name":"toUpperCase","return":"String","parameters":[]},{"declaring":"String","name":"toUpperCase","return":"String","parameters":["Locale"]},{"declaring":"String","name":"trim","return":"String","parameters":[]}],"static_fields":[],"fields":[]},{"name":"DenseVectorScriptDocValues","imported":true,"constructors":[],"static_methods":[],"methods":[{"declaring":"Collection","name":"add","return":"boolean","parameters":["def"]},{"declaring":"List","name":"add","return":"void","parameters":["int","def"]},{"declaring":"Collection","name":"addAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"addAll","return":"boolean","parameters":["int","Collection"]},{"declaring":null,"name":"any","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"asCollection","return":"Collection","parameters":[]},{"declaring":null,"name":"asList","return":"List","parameters":[]},{"declaring":"Collection","name":"clear","return":"void","parameters":[]},{"declaring":null,"name":"collect","return":"List","parameters":["Function"]},{"declaring":null,"name":"collect","return":"def","parameters":["Collection","Function"]},{"declaring":"Collection","name":"contains","return":"boolean","parameters":["def"]},{"declaring":"Collection","name":"containsAll","return":"boolean","parameters":["Collection"]},{"declaring":null,"name":"each","return":"def","parameters":["Consumer"]},{"declaring":null,"name":"eachWithIndex","return":"def","parameters":["ObjIntConsumer"]},{"declaring":"List","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":null,"name":"every","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"find","return":"def","parameters":["Predicate"]},{"declaring":null,"name":"findAll","return":"List","parameters":["Predicate"]},{"declaring":null,"name":"findResult","return":"def","parameters":["Function"]},{"declaring":null,"name":"findResult","return":"def","parameters":["def","Function"]},{"declaring":null,"name":"findResults","return":"List","parameters":["Function"]},{"declaring":"Iterable","name":"forEach","return":"void","parameters":["Consumer"]},{"declaring":"List","name":"get","return":"def","parameters":["int"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String","Object"]},{"declaring":null,"name":"getLength","return":"int","parameters":[]},{"declaring":null,"name":"groupBy","return":"Map","parameters":["Function"]},{"declaring":"List","name":"hashCode","return":"int","parameters":[]},{"declaring":"List","name":"indexOf","return":"int","parameters":["def"]},{"declaring":"Collection","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"Iterable","name":"iterator","return":"Iterator","parameters":[]},{"declaring":null,"name":"join","return":"String","parameters":["String"]},{"declaring":"List","name":"lastIndexOf","return":"int","parameters":["def"]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":[]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":["int"]},{"declaring":"List","name":"remove","return":"def","parameters":["int"]},{"declaring":"Collection","name":"removeAll","return":"boolean","parameters":["Collection"]},{"declaring":"Collection","name":"removeIf","return":"boolean","parameters":["Predicate"]},{"declaring":"List","name":"replaceAll","return":"void","parameters":["UnaryOperator"]},{"declaring":"Collection","name":"retainAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"set","return":"def","parameters":["int","def"]},{"declaring":"Collection","name":"size","return":"int","parameters":[]},{"declaring":"List","name":"sort","return":"void","parameters":["Comparator"]},{"declaring":null,"name":"split","return":"List","parameters":["Predicate"]},{"declaring":"Collection","name":"spliterator","return":"Spliterator","parameters":[]},{"declaring":"Collection","name":"stream","return":"Stream","parameters":[]},{"declaring":"List","name":"subList","return":"List","parameters":["int","int"]},{"declaring":null,"name":"sum","return":"double","parameters":[]},{"declaring":null,"name":"sum","return":"double","parameters":["ToDoubleFunction"]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":[]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":["def[]"]},{"declaring":"Object","name":"toString","return":"String","parameters":[]}],"static_fields":[],"fields":[]},{"name":"VersionScriptDocValues","imported":true,"constructors":[],"static_methods":[],"methods":[{"declaring":"Collection","name":"add","return":"boolean","parameters":["def"]},{"declaring":"List","name":"add","return":"void","parameters":["int","def"]},{"declaring":"Collection","name":"addAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"addAll","return":"boolean","parameters":["int","Collection"]},{"declaring":null,"name":"any","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"asCollection","return":"Collection","parameters":[]},{"declaring":null,"name":"asList","return":"List","parameters":[]},{"declaring":"Collection","name":"clear","return":"void","parameters":[]},{"declaring":null,"name":"collect","return":"List","parameters":["Function"]},{"declaring":null,"name":"collect","return":"def","parameters":["Collection","Function"]},{"declaring":"Collection","name":"contains","return":"boolean","parameters":["def"]},{"declaring":"Collection","name":"containsAll","return":"boolean","parameters":["Collection"]},{"declaring":null,"name":"each","return":"def","parameters":["Consumer"]},{"declaring":null,"name":"eachWithIndex","return":"def","parameters":["ObjIntConsumer"]},{"declaring":"List","name":"equals","return":"boolean","parameters":["Object"]},{"declaring":null,"name":"every","return":"boolean","parameters":["Predicate"]},{"declaring":null,"name":"find","return":"def","parameters":["Predicate"]},{"declaring":null,"name":"findAll","return":"List","parameters":["Predicate"]},{"declaring":null,"name":"findResult","return":"def","parameters":["Function"]},{"declaring":null,"name":"findResult","return":"def","parameters":["def","Function"]},{"declaring":null,"name":"findResults","return":"List","parameters":["Function"]},{"declaring":"Iterable","name":"forEach","return":"void","parameters":["Consumer"]},{"declaring":"VersionScriptDocValues","name":"get","return":"String","parameters":["int"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String"]},{"declaring":null,"name":"getByPath","return":"Object","parameters":["String","Object"]},{"declaring":null,"name":"getLength","return":"int","parameters":[]},{"declaring":"VersionScriptDocValues","name":"getValue","return":"String","parameters":[]},{"declaring":null,"name":"groupBy","return":"Map","parameters":["Function"]},{"declaring":"List","name":"hashCode","return":"int","parameters":[]},{"declaring":"List","name":"indexOf","return":"int","parameters":["def"]},{"declaring":"Collection","name":"isEmpty","return":"boolean","parameters":[]},{"declaring":"Iterable","name":"iterator","return":"Iterator","parameters":[]},{"declaring":null,"name":"join","return":"String","parameters":["String"]},{"declaring":"List","name":"lastIndexOf","return":"int","parameters":["def"]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":[]},{"declaring":"List","name":"listIterator","return":"ListIterator","parameters":["int"]},{"declaring":"List","name":"remove","return":"def","parameters":["int"]},{"declaring":"Collection","name":"removeAll","return":"boolean","parameters":["Collection"]},{"declaring":"Collection","name":"removeIf","return":"boolean","parameters":["Predicate"]},{"declaring":"List","name":"replaceAll","return":"void","parameters":["UnaryOperator"]},{"declaring":"Collection","name":"retainAll","return":"boolean","parameters":["Collection"]},{"declaring":"List","name":"set","return":"def","parameters":["int","def"]},{"declaring":"Collection","name":"size","return":"int","parameters":[]},{"declaring":"List","name":"sort","return":"void","parameters":["Comparator"]},{"declaring":null,"name":"split","return":"List","parameters":["Predicate"]},{"declaring":"Collection","name":"spliterator","return":"Spliterator","parameters":[]},{"declaring":"Collection","name":"stream","return":"Stream","parameters":[]},{"declaring":"List","name":"subList","return":"List","parameters":["int","int"]},{"declaring":null,"name":"sum","return":"double","parameters":[]},{"declaring":null,"name":"sum","return":"double","parameters":["ToDoubleFunction"]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":[]},{"declaring":"Collection","name":"toArray","return":"def[]","parameters":["def[]"]},{"declaring":"Object","name":"toString","return":"String","parameters":[]}],"static_fields":[],"fields":[]}],"imported_methods":[{"declaring":null,"name":"saturation","return":"double","parameters":["double","double"]},{"declaring":null,"name":"sigmoid","return":"double","parameters":["double","double","double"]}],"class_bindings":[{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$CosineSimilarity","name":"cosineSimilarity","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.lang.Object","java.lang.String"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateExp","name":"decayDateExp","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateGauss","name":"decayDateGauss","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayDateLinear","name":"decayDateLinear","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.script.JodaCompatibleZonedDateTime"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoExp","name":"decayGeoExp","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoGauss","name":"decayGeoGauss","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayGeoLinear","name":"decayGeoLinear","return":"double","read_only":4,"parameters":["java.lang.String","java.lang.String","java.lang.String","double","org.elasticsearch.common.geo.GeoPoint"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericExp","name":"decayNumericExp","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericGauss","name":"decayNumericGauss","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$DecayNumericLinear","name":"decayNumericLinear","return":"double","read_only":4,"parameters":["double","double","double","double","double"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$DotProduct","name":"dotProduct","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.lang.Object","java.lang.String"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$L1Norm","name":"l1norm","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.lang.Object","java.lang.String"]},{"declaring":"org.elasticsearch.script.VectorScoreScriptUtils$L2Norm","name":"l2norm","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","java.lang.Object","java.lang.String"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$RandomScoreDoc","name":"randomScore","return":"double","read_only":2,"parameters":["org.elasticsearch.script.ScoreScript","int"]},{"declaring":"org.elasticsearch.script.ScoreScriptUtils$RandomScoreField","name":"randomScore","return":"double","read_only":3,"parameters":["org.elasticsearch.script.ScoreScript","int","java.lang.String"]}],"instance_bindings":[]} diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.score.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.score.txt index e1769d28e226..b0506e7aa677 100644 --- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.score.txt +++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.score.txt @@ -27,9 +27,9 @@ static_import { double decayDateLinear(String, String, String, double, ZonedDateTime) bound_to org.elasticsearch.script.ScoreScriptUtils$DecayDateLinear double decayDateExp(String, String, String, double, ZonedDateTime) bound_to org.elasticsearch.script.ScoreScriptUtils$DecayDateExp double decayDateGauss(String, String, String, double, ZonedDateTime) bound_to org.elasticsearch.script.ScoreScriptUtils$DecayDateGauss - double l1norm(org.elasticsearch.script.ScoreScript, List, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$L1Norm - double l2norm(org.elasticsearch.script.ScoreScript, List, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$L2Norm - double cosineSimilarity(org.elasticsearch.script.ScoreScript, List, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$CosineSimilarity - double dotProduct(org.elasticsearch.script.ScoreScript, List, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$DotProduct + double l1norm(org.elasticsearch.script.ScoreScript, Object, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$L1Norm + double l2norm(org.elasticsearch.script.ScoreScript, Object, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$L2Norm + double cosineSimilarity(org.elasticsearch.script.ScoreScript, Object, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$CosineSimilarity + double dotProduct(org.elasticsearch.script.ScoreScript, Object, String) bound_to org.elasticsearch.script.VectorScoreScriptUtils$DotProduct } diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml index 6ac4ba01c34e..7d7f7fb01a7b 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml @@ -77,7 +77,35 @@ setup: - match: {hits.hits.2._id: "1"} - match: {hits.hits.2._score: 1632.0} +--- +"Dot Product hexidecimal": + - requires: + cluster_features: "gte_v8.15.0" + reason: "support for hexidecimal byte vectors added in 8.15" + - do: + headers: + Content-Type: application/json + search: + rest_total_hits_as_int: true + body: + query: + script_score: + query: {match_all: {} } + script: + source: "dotProduct(params.query_vector, 'vector')" + params: + query_vector: "006ff30e84" + - match: {hits.total: 3} + + - match: {hits.hits.0._id: "2"} + - match: {hits.hits.0._score: 28732.0} + + - match: {hits.hits.1._id: "3"} + - match: {hits.hits.1._score: 17439.0} + + - match: {hits.hits.2._id: "1"} + - match: {hits.hits.2._score: 1632.0} --- "Cosine Similarity": - do: @@ -108,6 +136,39 @@ setup: - gte: {hits.hits.2._score: 0.509} - lte: {hits.hits.2._score: 0.512} +--- +"Cosine Similarity hexidecimal": + - requires: + cluster_features: "gte_v8.15.0" + reason: "support for hexidecimal byte vectors added in 8.15" + - do: + headers: + Content-Type: application/json + search: + rest_total_hits_as_int: true + body: + query: + script_score: + query: {match_all: {} } + script: + source: "cosineSimilarity(params.query_vector, 'vector')" + params: + query_vector: "006ff30e84" + + - match: {hits.total: 3} + + - match: {hits.hits.0._id: "2"} + - gte: {hits.hits.0._score: 0.995} + - lte: {hits.hits.0._score: 0.998} + + - match: {hits.hits.1._id: "3"} + - gte: {hits.hits.1._score: 0.829} + - lte: {hits.hits.1._score: 0.832} + + - match: {hits.hits.2._id: "1"} + - gte: {hits.hits.2._score: 0.509} + - lte: {hits.hits.2._score: 0.512} + --- "Cosine similarity with indexed vector": - do: diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml index c3d008ea69d0..add9356df703 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml @@ -70,6 +70,35 @@ setup: - gte: {hits.hits.2._score: 29.0} --- +"L1 norm hexidecimal": + - requires: + cluster_features: "gte_v8.15.0" + reason: "support for hexidecimal byte vectors added in 8.15" + - do: + headers: + Content-Type: application/json + search: + rest_total_hits_as_int: true + body: + query: + script_score: + query: {match_all: {} } + script: + source: "l1norm(params.query_vector, 'my_dense_vector')" + params: + query_vector: "006ff30e84" + + - match: {hits.total: 3} + + - match: {hits.hits.0._id: "1"} + - match: {hits.hits.0._score: 246.0} + + - match: {hits.hits.1._id: "3"} + - match: {hits.hits.1._score: 117.0} + + - match: {hits.hits.2._id: "2"} + - gte: {hits.hits.2._score: 29.0} +--- "L2 norm": - do: headers: @@ -95,6 +124,38 @@ setup: - gte: {hits.hits.1._score: 94.407} - lte: {hits.hits.1._score: 94.41} + - match: {hits.hits.2._id: "2"} + - gte: {hits.hits.2._score: 15.263} + - lte: {hits.hits.2._score: 15.266} +--- +"L2 norm hexidecimal": + - requires: + cluster_features: "gte_v8.15.0" + reason: "support for hexidecimal byte vectors added in 8.15" + - do: + headers: + Content-Type: application/json + search: + rest_total_hits_as_int: true + body: + query: + script_score: + query: {match_all: {} } + script: + source: "l2norm(params.query_vector, 'my_dense_vector')" + params: + query_vector: "006ff30e84" + + - match: {hits.total: 3} + + - match: {hits.hits.0._id: "1"} + - gte: {hits.hits.0._score: 158.624} + - lte: {hits.hits.0._score: 158.627} + + - match: {hits.hits.1._id: "3"} + - gte: {hits.hits.1._score: 94.407} + - lte: {hits.hits.1._score: 94.41} + - match: {hits.hits.2._id: "2"} - gte: {hits.hits.2._score: 15.263} - lte: {hits.hits.2._score: 15.266} diff --git a/server/src/main/java/org/elasticsearch/script/VectorScoreScriptUtils.java b/server/src/main/java/org/elasticsearch/script/VectorScoreScriptUtils.java index f5d4a3d66be4..b071739321ea 100644 --- a/server/src/main/java/org/elasticsearch/script/VectorScoreScriptUtils.java +++ b/server/src/main/java/org/elasticsearch/script/VectorScoreScriptUtils.java @@ -13,6 +13,7 @@ import org.elasticsearch.script.field.vectors.DenseVector; import org.elasticsearch.script.field.vectors.DenseVectorDocValuesField; import java.io.IOException; +import java.util.HexFormat; import java.util.List; public class VectorScoreScriptUtils { @@ -65,6 +66,23 @@ public class VectorScoreScriptUtils { this.qvMagnitude = (float) Math.sqrt(queryMagnitude); field.getElementType().checkVectorBounds(validateValues); } + + /** + * Constructs a dense vector function used for byte-sized vectors. + * + * @param scoreScript The script in which this function was referenced. + * @param field The vector field. + * @param queryVector The query vector. + */ + public ByteDenseVectorFunction(ScoreScript scoreScript, DenseVectorDocValuesField field, byte[] queryVector) { + super(scoreScript, field); + this.queryVector = queryVector; + float queryMagnitude = 0.0f; + for (byte value : queryVector) { + queryMagnitude += value * value; + } + this.qvMagnitude = (float) Math.sqrt(queryMagnitude); + } } public static class FloatDenseVectorFunction extends DenseVectorFunction { @@ -116,6 +134,10 @@ public class VectorScoreScriptUtils { super(scoreScript, field, queryVector); } + public ByteL1Norm(ScoreScript scoreScript, DenseVectorDocValuesField field, byte[] queryVector) { + super(scoreScript, field, queryVector); + } + public double l1norm() { setNextVector(); return field.get().l1Norm(queryVector); @@ -138,11 +160,25 @@ public class VectorScoreScriptUtils { private final L1NormInterface function; - public L1Norm(ScoreScript scoreScript, List queryVector, String fieldName) { + @SuppressWarnings("unchecked") + public L1Norm(ScoreScript scoreScript, Object queryVector, String fieldName) { DenseVectorDocValuesField field = (DenseVectorDocValuesField) scoreScript.field(fieldName); function = switch (field.getElementType()) { - case BYTE -> new ByteL1Norm(scoreScript, field, queryVector); - case FLOAT -> new FloatL1Norm(scoreScript, field, queryVector); + case BYTE -> { + if (queryVector instanceof List) { + yield new ByteL1Norm(scoreScript, field, (List) queryVector); + } else if (queryVector instanceof String s) { + byte[] parsedQueryVector = HexFormat.of().parseHex(s); + yield new ByteL1Norm(scoreScript, field, parsedQueryVector); + } + throw new IllegalArgumentException("Unsupported input object for byte vectors: " + queryVector.getClass().getName()); + } + case FLOAT -> { + if (queryVector instanceof List) { + yield new FloatL1Norm(scoreScript, field, (List) queryVector); + } + throw new IllegalArgumentException("Unsupported input object for float vectors: " + queryVector.getClass().getName()); + } }; } @@ -162,6 +198,10 @@ public class VectorScoreScriptUtils { super(scoreScript, field, queryVector); } + public ByteL2Norm(ScoreScript scoreScript, DenseVectorDocValuesField field, byte[] queryVector) { + super(scoreScript, field, queryVector); + } + public double l2norm() { setNextVector(); return field.get().l2Norm(queryVector); @@ -184,11 +224,25 @@ public class VectorScoreScriptUtils { private final L2NormInterface function; - public L2Norm(ScoreScript scoreScript, List queryVector, String fieldName) { + @SuppressWarnings("unchecked") + public L2Norm(ScoreScript scoreScript, Object queryVector, String fieldName) { DenseVectorDocValuesField field = (DenseVectorDocValuesField) scoreScript.field(fieldName); function = switch (field.getElementType()) { - case BYTE -> new ByteL2Norm(scoreScript, field, queryVector); - case FLOAT -> new FloatL2Norm(scoreScript, field, queryVector); + case BYTE -> { + if (queryVector instanceof List) { + yield new ByteL2Norm(scoreScript, field, (List) queryVector); + } else if (queryVector instanceof String s) { + byte[] parsedQueryVector = HexFormat.of().parseHex(s); + yield new ByteL2Norm(scoreScript, field, parsedQueryVector); + } + throw new IllegalArgumentException("Unsupported input object for byte vectors: " + queryVector.getClass().getName()); + } + case FLOAT -> { + if (queryVector instanceof List) { + yield new FloatL2Norm(scoreScript, field, (List) queryVector); + } + throw new IllegalArgumentException("Unsupported input object for float vectors: " + queryVector.getClass().getName()); + } }; } @@ -208,6 +262,10 @@ public class VectorScoreScriptUtils { super(scoreScript, field, queryVector); } + public ByteDotProduct(ScoreScript scoreScript, DenseVectorDocValuesField field, byte[] queryVector) { + super(scoreScript, field, queryVector); + } + public double dotProduct() { setNextVector(); return field.get().dotProduct(queryVector); @@ -230,11 +288,25 @@ public class VectorScoreScriptUtils { private final DotProductInterface function; - public DotProduct(ScoreScript scoreScript, List queryVector, String fieldName) { + @SuppressWarnings("unchecked") + public DotProduct(ScoreScript scoreScript, Object queryVector, String fieldName) { DenseVectorDocValuesField field = (DenseVectorDocValuesField) scoreScript.field(fieldName); function = switch (field.getElementType()) { - case BYTE -> new ByteDotProduct(scoreScript, field, queryVector); - case FLOAT -> new FloatDotProduct(scoreScript, field, queryVector); + case BYTE -> { + if (queryVector instanceof List) { + yield new ByteDotProduct(scoreScript, field, (List) queryVector); + } else if (queryVector instanceof String s) { + byte[] parsedQueryVector = HexFormat.of().parseHex(s); + yield new ByteDotProduct(scoreScript, field, parsedQueryVector); + } + throw new IllegalArgumentException("Unsupported input object for byte vectors: " + queryVector.getClass().getName()); + } + case FLOAT -> { + if (queryVector instanceof List) { + yield new FloatDotProduct(scoreScript, field, (List) queryVector); + } + throw new IllegalArgumentException("Unsupported input object for float vectors: " + queryVector.getClass().getName()); + } }; } @@ -254,6 +326,10 @@ public class VectorScoreScriptUtils { super(scoreScript, field, queryVector); } + public ByteCosineSimilarity(ScoreScript scoreScript, DenseVectorDocValuesField field, byte[] queryVector) { + super(scoreScript, field, queryVector); + } + public double cosineSimilarity() { setNextVector(); return field.get().cosineSimilarity(queryVector, qvMagnitude); @@ -276,11 +352,25 @@ public class VectorScoreScriptUtils { private final CosineSimilarityInterface function; - public CosineSimilarity(ScoreScript scoreScript, List queryVector, String fieldName) { + @SuppressWarnings("unchecked") + public CosineSimilarity(ScoreScript scoreScript, Object queryVector, String fieldName) { DenseVectorDocValuesField field = (DenseVectorDocValuesField) scoreScript.field(fieldName); function = switch (field.getElementType()) { - case BYTE -> new ByteCosineSimilarity(scoreScript, field, queryVector); - case FLOAT -> new FloatCosineSimilarity(scoreScript, field, queryVector); + case BYTE -> { + if (queryVector instanceof List) { + yield new ByteCosineSimilarity(scoreScript, field, (List) queryVector); + } else if (queryVector instanceof String s) { + byte[] parsedQueryVector = HexFormat.of().parseHex(s); + yield new ByteCosineSimilarity(scoreScript, field, parsedQueryVector); + } + throw new IllegalArgumentException("Unsupported input object for byte vectors: " + queryVector.getClass().getName()); + } + case FLOAT -> { + if (queryVector instanceof List) { + yield new FloatCosineSimilarity(scoreScript, field, (List) queryVector); + } + throw new IllegalArgumentException("Unsupported input object for float vectors: " + queryVector.getClass().getName()); + } }; } diff --git a/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java b/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java index df9f4384719e..a095c4e6409a 100644 --- a/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java +++ b/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.test.ESTestCase; import java.io.IOException; import java.util.Arrays; +import java.util.HexFormat; import java.util.List; import static org.hamcrest.Matchers.containsString; @@ -128,6 +129,7 @@ public class VectorScoreScriptUtilsTests extends ESTestCase { float[] docVector = new float[] { 1, 127, -128, 5, -10 }; List queryVector = Arrays.asList((byte) 1, (byte) 125, (byte) -12, (byte) 2, (byte) 4); List invalidQueryVector = Arrays.asList((byte) 1, (byte) 1); + String hexidecimalString = HexFormat.of().formatHex(new byte[] { 1, 125, -12, 2, 4 }); List fields = List.of( new ByteBinaryDenseVectorDocValuesField( @@ -154,6 +156,14 @@ public class VectorScoreScriptUtilsTests extends ESTestCase { 0.001 ); + function = new CosineSimilarity(scoreScript, hexidecimalString, fieldName); + assertEquals( + "cosineSimilarity result is not equal to the expected value!", + cosineSimilarityExpected, + function.cosineSimilarity(), + 0.001 + ); + // Test normalization for cosineSimilarity float[] queryVectorArray = new float[queryVector.size()]; for (int i = 0; i < queryVectorArray.length; i++) { @@ -191,10 +201,13 @@ public class VectorScoreScriptUtilsTests extends ESTestCase { ); // Check scripting infrastructure integration - DotProduct dotProduct = new DotProduct(scoreScript, queryVector, fieldName); - assertEquals(17382.0, dotProduct.dotProduct(), 0.001); + assertEquals(17382.0, new DotProduct(scoreScript, queryVector, fieldName).dotProduct(), 0.001); + assertEquals(17382.0, new DotProduct(scoreScript, hexidecimalString, fieldName).dotProduct(), 0.001); assertEquals(135.0, new L1Norm(scoreScript, queryVector, fieldName).l1norm(), 0.001); + assertEquals(135.0, new L1Norm(scoreScript, hexidecimalString, fieldName).l1norm(), 0.001); assertEquals(116.897, new L2Norm(scoreScript, queryVector, fieldName).l2norm(), 0.001); + assertEquals(116.897, new L2Norm(scoreScript, hexidecimalString, fieldName).l2norm(), 0.001); + DotProduct dotProduct = new DotProduct(scoreScript, queryVector, fieldName); when(scoreScript._getDocId()).thenReturn(1); e = expectThrows(IllegalArgumentException.class, dotProduct::dotProduct); assertEquals("A document doesn't have a value for a vector field!", e.getMessage()); From 98b0842d02363b52a487783c6d4eb75c6d0f1dc0 Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:46:35 -0400 Subject: [PATCH 18/34] [ML] Fixing inference API elasticsearch service task type always set to rerank (#109592) * Fixing rerank hard coded task type for eland * Update docs/changelog/109592.yaml * Delete docs/changelog/109592.yaml * Randomizing task type for tests --- .../ElasticsearchInternalService.java | 10 +--- .../ElasticsearchInternalServiceTests.java | 56 +++++++++++++++++-- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java index df546efd161e..dbc36960a823 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java @@ -132,16 +132,10 @@ public class ElasticsearchInternalService implements InferenceService { ).build(); throwIfNotEmptyMap(serviceSettingsMap, name()); - var taskSettings = CustomElandModel.taskSettingsFromMap(TaskType.RERANK, taskSettingsMap); + var taskSettings = CustomElandModel.taskSettingsFromMap(taskType, taskSettingsMap); throwIfNotEmptyMap(taskSettingsMap, name()); - var model = CustomElandModel.build( - inferenceEntityId, - TaskType.RERANK, - name(), - customElandInternalServiceSettings, - taskSettings - ); + var model = CustomElandModel.build(inferenceEntityId, taskType, name(), customElandInternalServiceSettings, taskSettings); delegate.onResponse(model); } }); diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalServiceTests.java index e34ce410bbab..dfcfe466c2a3 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalServiceTests.java @@ -11,7 +11,9 @@ package org.elasticsearch.xpack.inference.services.elasticsearch; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.client.internal.Client; +import org.elasticsearch.core.TimeValue; import org.elasticsearch.inference.ChunkedInferenceServiceResults; import org.elasticsearch.inference.ChunkingOptions; import org.elasticsearch.inference.InferenceResults; @@ -55,7 +57,6 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -63,6 +64,7 @@ import java.util.concurrent.atomic.AtomicReference; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doAnswer; @@ -83,7 +85,7 @@ public class ElasticsearchInternalServiceTests extends ESTestCase { @After public void shutdownThreadPool() { - TestThreadPool.terminate(threadPool, 30, TimeUnit.SECONDS); + terminate(threadPool); } public void testParseRequestConfig() { @@ -290,7 +292,7 @@ public class ElasticsearchInternalServiceTests extends ESTestCase { assertEquals(returnDocs, ((CustomElandRerankTaskSettings) model.getTaskSettings()).returnDocuments()); }, e -> { fail("Model parsing failed " + e.getMessage()); }); - service.parseRequestConfig(randomInferenceEntityId, taskType, settings, Set.of(), modelListener); + service.parseRequestConfig(randomInferenceEntityId, TaskType.RERANK, settings, Set.of(), modelListener); } } @@ -332,7 +334,7 @@ public class ElasticsearchInternalServiceTests extends ESTestCase { assertEquals(Boolean.TRUE, ((CustomElandRerankTaskSettings) model.getTaskSettings()).returnDocuments()); }, e -> { fail("Model parsing failed " + e.getMessage()); }); - service.parseRequestConfig(randomInferenceEntityId, taskType, settings, Set.of(), modelListener); + service.parseRequestConfig(randomInferenceEntityId, TaskType.RERANK, settings, Set.of(), modelListener); } } @@ -671,6 +673,52 @@ public class ElasticsearchInternalServiceTests extends ESTestCase { } } + public void testParseRequestConfigEland_PreservesTaskType() { + var client = mock(Client.class); + doAnswer(invocationOnMock -> { + @SuppressWarnings("unchecked") + ActionListener listener = (ActionListener) invocationOnMock + .getArguments()[2]; + listener.onResponse( + new GetTrainedModelsAction.Response(new QueryPage<>(List.of(mock(TrainedModelConfig.class)), 1, mock(ParseField.class))) + ); + return Void.TYPE; + }).when(client).execute(any(), any(), any()); + when(client.threadPool()).thenReturn(threadPool); + + var service = createService(client); + var settings = new HashMap(); + settings.put( + ModelConfigurations.SERVICE_SETTINGS, + new HashMap<>( + Map.of( + ElasticsearchInternalServiceSettings.NUM_ALLOCATIONS, + 1, + ElasticsearchInternalServiceSettings.NUM_THREADS, + 4, + InternalServiceSettings.MODEL_ID, + "custom-model" + ) + ) + ); + + var serviceSettings = new CustomElandInternalServiceSettings(1, 4, "custom-model"); + var taskType = randomFrom(TaskType.values()); + var taskSettings = taskType == TaskType.RERANK ? CustomElandRerankTaskSettings.DEFAULT_SETTINGS : null; + var expectedModel = CustomElandModel.build( + randomInferenceEntityId, + taskType, + ElasticsearchInternalService.NAME, + serviceSettings, + taskSettings + ); + + PlainActionFuture listener = new PlainActionFuture<>(); + service.parseRequestConfig(randomInferenceEntityId, taskType, settings, Set.of(), listener); + var model = listener.actionGet(TimeValue.THIRTY_SECONDS); + assertThat(model, is(expectedModel)); + } + public void testBuildInferenceRequest() { var id = randomAlphaOfLength(5); var inputs = randomList(1, 3, () -> randomAlphaOfLength(4)); From f9c4e90609e452261ca92cafd72bf7584c7f8820 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 11 Jun 2024 16:57:48 -0400 Subject: [PATCH 19/34] Adjust bwc version after #109492 backport (#109596) blocked by: https://github.com/elastic/elasticsearch/pull/109595 related to: #109492 --- .../test/painless/145_dense_vector_byte_basic.yml | 8 ++++---- .../test/painless/155_dense_vector_byte_l1l2.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml index 7d7f7fb01a7b..4eb8df25c27b 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/145_dense_vector_byte_basic.yml @@ -80,8 +80,8 @@ setup: --- "Dot Product hexidecimal": - requires: - cluster_features: "gte_v8.15.0" - reason: "support for hexidecimal byte vectors added in 8.15" + cluster_features: "gte_v8.14.1" + reason: "support for hexidecimal byte vectors added in 8.14" - do: headers: Content-Type: application/json @@ -139,8 +139,8 @@ setup: --- "Cosine Similarity hexidecimal": - requires: - cluster_features: "gte_v8.15.0" - reason: "support for hexidecimal byte vectors added in 8.15" + cluster_features: "gte_v8.14.1" + reason: "support for hexidecimal byte vectors added in 8.14" - do: headers: Content-Type: application/json diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml index add9356df703..46075c5db744 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/155_dense_vector_byte_l1l2.yml @@ -72,8 +72,8 @@ setup: --- "L1 norm hexidecimal": - requires: - cluster_features: "gte_v8.15.0" - reason: "support for hexidecimal byte vectors added in 8.15" + cluster_features: "gte_v8.14.1" + reason: "support for hexidecimal byte vectors added in 8.14" - do: headers: Content-Type: application/json @@ -130,8 +130,8 @@ setup: --- "L2 norm hexidecimal": - requires: - cluster_features: "gte_v8.15.0" - reason: "support for hexidecimal byte vectors added in 8.15" + cluster_features: "gte_v8.14.1" + reason: "support for hexidecimal byte vectors added in 8.14" - do: headers: Content-Type: application/json From 113087ea74fbd1fb00c281fc0693c10d86fc3cd5 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 11 Jun 2024 17:06:32 -0400 Subject: [PATCH 20/34] ESQL: Move serialization for unary functions (#109436) This moves the serialization for unary functions from `PlanNamedTypes` to the classes themselves which lines up more with how the rest of Elasticsearch works. There's a little more ceremony as the subclasses themselves declare serialization constructors. *EVERY* subclass does. And has to declare `getWriteableName`. Now, those serialization ctors are just `super(in);` so you can't screw it up, but they are there and that's more than before. But, again, it's what folks coming from the rest of Elasticsearch will expect. There is some silver lining here - it's much easier to make wire changes with these serialization ctors. And, maybe better, it's very easy to *know* that this class goes over the wire - it has a serialization ctor. It's right there, staring at you. There are other ways to do this, but I chose to put the serialization ctors right in the class for the three reasons above. --- .../esql/core/expression/Expression.java | 17 +- .../function/scalar/UnaryScalarFunction.java | 102 +++++++++++ .../convert/AbstractConvertFunction.java | 7 + .../function/scalar/convert/FromBase64.java | 17 ++ .../function/scalar/convert/ToBase64.java | 12 ++ .../function/scalar/convert/ToBoolean.java | 17 ++ .../scalar/convert/ToCartesianPoint.java | 17 ++ .../scalar/convert/ToCartesianShape.java | 17 ++ .../function/scalar/convert/ToDatetime.java | 17 ++ .../function/scalar/convert/ToDegrees.java | 18 ++ .../function/scalar/convert/ToDouble.java | 13 ++ .../function/scalar/convert/ToGeoPoint.java | 17 ++ .../function/scalar/convert/ToGeoShape.java | 17 ++ .../function/scalar/convert/ToIP.java | 13 ++ .../function/scalar/convert/ToInteger.java | 17 ++ .../function/scalar/convert/ToLong.java | 13 ++ .../function/scalar/convert/ToRadians.java | 18 ++ .../function/scalar/convert/ToString.java | 13 ++ .../scalar/convert/ToUnsignedLong.java | 17 ++ .../function/scalar/convert/ToVersion.java | 17 ++ .../expression/function/scalar/math/Abs.java | 14 ++ .../math/AbstractTrigonometricFunction.java | 6 + .../expression/function/scalar/math/Acos.java | 14 ++ .../expression/function/scalar/math/Asin.java | 14 ++ .../expression/function/scalar/math/Atan.java | 14 ++ .../expression/function/scalar/math/Cbrt.java | 14 ++ .../expression/function/scalar/math/Ceil.java | 14 ++ .../expression/function/scalar/math/Cos.java | 14 ++ .../expression/function/scalar/math/Cosh.java | 14 ++ .../function/scalar/math/Floor.java | 14 ++ .../function/scalar/math/Log10.java | 14 ++ .../function/scalar/math/Signum.java | 14 ++ .../expression/function/scalar/math/Sin.java | 13 ++ .../expression/function/scalar/math/Sinh.java | 14 ++ .../expression/function/scalar/math/Sqrt.java | 14 ++ .../expression/function/scalar/math/Tan.java | 14 ++ .../expression/function/scalar/math/Tanh.java | 14 ++ .../function/scalar/package-info.java | 20 ++- .../function/scalar/spatial/StX.java | 14 ++ .../function/scalar/spatial/StY.java | 14 ++ .../function/scalar/string/LTrim.java | 14 ++ .../function/scalar/string/Length.java | 13 ++ .../function/scalar/string/RTrim.java | 14 ++ .../function/scalar/string/Trim.java | 14 ++ .../predicate/operator/arithmetic/Neg.java | 17 +- .../esql/io/stream/PlanNameRegistry.java | 17 +- .../xpack/esql/io/stream/PlanNamedTypes.java | 163 ++---------------- .../xpack/esql/plugin/EsqlPlugin.java | 2 +- .../AbstractExpressionSerializationTests.java | 90 ++++++++++ ...AbstractUnaryScalarSerializationTests.java | 36 ++++ .../convert/FromBase64SerializationTests.java | 19 ++ .../convert/ToBase64SerializationTests.java | 19 ++ .../convert/ToBooleanSerializationTests.java | 19 ++ .../ToCartesianPointSerializationTests.java | 19 ++ .../ToCartesianShapeSerializationTests.java | 19 ++ .../convert/ToDatetimeSerializationTests.java | 19 ++ .../convert/ToDegreesSerializationTests.java | 19 ++ .../convert/ToDoubleSerializationTests.java | 19 ++ .../convert/ToGeoPointSerializationTests.java | 19 ++ .../convert/ToGeoShapeSerializationTests.java | 19 ++ .../convert/ToIPSerializationTests.java | 19 ++ .../convert/ToIntegerSerializationTests.java | 19 ++ .../convert/ToLongSerializationTests.java | 19 ++ .../convert/ToRadiansSerializationTests.java | 19 ++ .../convert/ToStringSerializationTests.java | 19 ++ .../ToUnsignedLongSerializationTests.java | 19 ++ .../convert/ToVersionSerializationTests.java | 19 ++ .../scalar/math/AbsSerializationTests.java | 19 ++ .../scalar/math/AcosSerializationTests.java | 19 ++ .../scalar/math/AsinSerializationTests.java | 19 ++ .../scalar/math/AtanSerializationTests.java | 19 ++ .../scalar/math/CbrtSerializationTests.java | 19 ++ .../scalar/math/CeilSerializationTests.java | 19 ++ .../scalar/math/CosSerializationTests.java | 19 ++ .../scalar/math/CoshSerializationTests.java | 19 ++ .../scalar/math/FloorSerializationTests.java | 19 ++ .../scalar/math/Log10SerializationTests.java | 19 ++ .../scalar/math/SinSerializationTests.java | 19 ++ .../scalar/math/SinhSerializationTests.java | 19 ++ .../scalar/math/SqrtSerializationTests.java | 19 ++ .../scalar/math/TanSerializationTests.java | 19 ++ .../scalar/math/TanhSerializationTests.java | 19 ++ .../arithmetic/NegSerializationTests.java | 19 ++ .../esql/io/stream/PlanNamedTypesTests.java | 2 +- 84 files changed, 1519 insertions(+), 163 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractExpressionSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractUnaryScalarSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64SerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64SerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBooleanSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPointSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShapeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegreesSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDoubleSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPointSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIPSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadiansSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLongSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersionSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbsSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AcosSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AsinSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AtanSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CbrtSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CeilSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/FloorSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10SerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SqrtSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/NegSerializationTests.java diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expression.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expression.java index 00765a8c0528..ee7e0aa81f81 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expression.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expression.java @@ -6,6 +6,8 @@ */ package org.elasticsearch.xpack.esql.core.expression; +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.esql.core.QlIllegalArgumentException; import org.elasticsearch.xpack.esql.core.capabilities.Resolvable; import org.elasticsearch.xpack.esql.core.capabilities.Resolvables; @@ -14,6 +16,7 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.util.StringUtils; +import java.io.IOException; import java.util.List; import java.util.function.Supplier; @@ -26,7 +29,7 @@ import java.util.function.Supplier; * a, b, ABS(c), and i are all Expressions, with ABS(c) being a Function * (which is a type of expression) with a single child, c. */ -public abstract class Expression extends Node implements Resolvable { +public abstract class Expression extends Node implements Resolvable, NamedWriteable { public static class TypeResolution { private final boolean failed; @@ -78,6 +81,18 @@ public abstract class Expression extends Node implements Resolvable super(source, children); } + @Override + public void writeTo(StreamOutput out) throws IOException { + // TODO remove this function entirely once all subclasses implement it + throw new UnsupportedOperationException("todo unsupported"); + } + + @Override + public String getWriteableName() { + // TODO remove this function entirely once all subclasses implement it + throw new UnsupportedOperationException("todo unsupported"); + } + // whether the expression can be evaluated statically (folded) or not public boolean foldable() { return false; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/UnaryScalarFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/UnaryScalarFunction.java index 2e29162aebb4..0866f97b6772 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/UnaryScalarFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/UnaryScalarFunction.java @@ -7,16 +7,108 @@ package org.elasticsearch.xpack.esql.expression.function.scalar; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.TypeResolutions; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.FromBase64; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToBase64; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToBoolean; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianPoint; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDatetime; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDegrees; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoPoint; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIP; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToRadians; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToString; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToUnsignedLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToVersion; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Acos; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Asin; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Atan; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cbrt; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Ceil; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cos; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cosh; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Floor; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log10; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Signum; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sin; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sinh; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sqrt; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tan; +import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tanh; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StY; +import org.elasticsearch.xpack.esql.expression.function.scalar.string.LTrim; +import org.elasticsearch.xpack.esql.expression.function.scalar.string.Length; +import org.elasticsearch.xpack.esql.expression.function.scalar.string.RTrim; +import org.elasticsearch.xpack.esql.expression.function.scalar.string.Trim; +import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Neg; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; +import java.io.IOException; import java.util.Arrays; +import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNumeric; public abstract class UnaryScalarFunction extends EsqlScalarFunction { + public static List getNamedWriteables() { + return List.of( + Abs.ENTRY, + Acos.ENTRY, + Asin.ENTRY, + Atan.ENTRY, + Cbrt.ENTRY, + Ceil.ENTRY, + Cos.ENTRY, + Cosh.ENTRY, + Floor.ENTRY, + FromBase64.ENTRY, + Length.ENTRY, + Log10.ENTRY, + LTrim.ENTRY, + Neg.ENTRY, + RTrim.ENTRY, + Signum.ENTRY, + Sin.ENTRY, + Sinh.ENTRY, + Sqrt.ENTRY, + StX.ENTRY, + StY.ENTRY, + Tan.ENTRY, + Tanh.ENTRY, + ToBase64.ENTRY, + ToBoolean.ENTRY, + ToCartesianPoint.ENTRY, + ToDatetime.ENTRY, + ToDegrees.ENTRY, + ToDouble.ENTRY, + ToGeoShape.ENTRY, + ToCartesianShape.ENTRY, + ToGeoPoint.ENTRY, + ToIP.ENTRY, + ToInteger.ENTRY, + ToLong.ENTRY, + ToRadians.ENTRY, + ToString.ENTRY, + ToUnsignedLong.ENTRY, + ToVersion.ENTRY, + Trim.ENTRY + ); + } + protected final Expression field; public UnaryScalarFunction(Source source, Expression field) { @@ -24,6 +116,16 @@ public abstract class UnaryScalarFunction extends EsqlScalarFunction { this.field = field; } + protected UnaryScalarFunction(StreamInput in) throws IOException { + this(Source.readFrom((PlanStreamInput) in), ((PlanStreamInput) in).readExpression()); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + source().writeTo(out); + ((PlanStreamOutput) out).writeExpression(field); + } + @Override protected Expression.TypeResolution resolveType() { if (childrenResolved() == false) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java index f1d0256a1f1c..2496d8b82fa6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java @@ -11,6 +11,7 @@ import joptsimple.internal.Strings; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.data.Vector; @@ -24,8 +25,10 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.Warnings; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; import org.elasticsearch.xpack.esql.type.EsqlDataTypes; +import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -53,6 +56,10 @@ public abstract class AbstractConvertFunction extends UnaryScalarFunction { super(source, field); } + protected AbstractConvertFunction(StreamInput in) throws IOException { + this(Source.readFrom((PlanStreamInput) in), ((PlanStreamInput) in).readExpression()); + } + /** * Build the evaluator given the evaluator a multivalued field. */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64.java index 2ebc3d824a4e..873d496bfc8f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.ann.Fixed; import org.elasticsearch.compute.operator.EvalOperator; @@ -24,6 +26,7 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; import org.elasticsearch.xpack.esql.planner.PlannerUtils; +import java.io.IOException; import java.util.Base64; import java.util.List; import java.util.function.Function; @@ -32,6 +35,11 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; public class FromBase64 extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "FromBase64", + FromBase64::new + ); @FunctionInfo( returnType = "keyword", @@ -53,6 +61,15 @@ public class FromBase64 extends UnaryScalarFunction { return isString(field, sourceText(), TypeResolutions.ParamOrdinal.DEFAULT); } + private FromBase64(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public DataType dataType() { return KEYWORD; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64.java index f24651337550..ab8287413c61 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.ann.Fixed; import org.elasticsearch.compute.operator.EvalOperator; @@ -24,6 +26,7 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; import org.elasticsearch.xpack.esql.planner.PlannerUtils; +import java.io.IOException; import java.util.Base64; import java.util.List; import java.util.function.Function; @@ -32,6 +35,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; public class ToBase64 extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToBase64", ToBase64::new); @FunctionInfo( returnType = "keyword", @@ -40,7 +44,15 @@ public class ToBase64 extends UnaryScalarFunction { ) public ToBase64(Source source, @Param(name = "string", type = { "keyword", "text" }, description = "A string.") Expression string) { super(source, string); + } + private ToBase64(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBoolean.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBoolean.java index 5de31b7f114e..06cc99345643 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBoolean.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBoolean.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -31,6 +34,11 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToBo import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToBoolean; public class ToBoolean extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToBoolean", + ToBoolean::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(BOOLEAN, (field, source) -> field), @@ -62,6 +70,15 @@ public class ToBoolean extends AbstractConvertFunction { super(source, field); } + private ToBoolean(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPoint.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPoint.java index 9a3362c52c0f..60a25fc91d50 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPoint.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPoint.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -26,6 +29,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToSpatial; public class ToCartesianPoint extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToCartesianPoint", + ToCartesianPoint::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(CARTESIAN_POINT, (fieldEval, source) -> fieldEval), @@ -52,6 +60,15 @@ public class ToCartesianPoint extends AbstractConvertFunction { super(source, field); } + private ToCartesianPoint(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShape.java index 03e8c565f342..03ac4bdf4824 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShape.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -27,6 +30,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToSpatial; public class ToCartesianShape extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToCartesianShape", + ToCartesianShape::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(CARTESIAN_POINT, (fieldEval, source) -> fieldEval), @@ -54,6 +62,15 @@ public class ToCartesianShape extends AbstractConvertFunction { super(source, field); } + private ToCartesianShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetime.java index 53c87427b960..917abc9d7716 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetime.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -30,6 +33,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToLong; public class ToDatetime extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToDatetime", + ToDatetime::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(DATETIME, (field, source) -> field), @@ -80,6 +88,15 @@ public class ToDatetime extends AbstractConvertFunction { super(source, field); } + private ToDatetime(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegrees.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegrees.java index af163b6ff878..4eb6662e3e97 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegrees.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegrees.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -31,6 +34,12 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; * to degrees. */ public class ToDegrees extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToDegrees", + ToDegrees::new + ); + private static final Map EVALUATORS = Map.ofEntries( Map.entry(DOUBLE, ToDegreesEvaluator.Factory::new), Map.entry(INTEGER, (field, source) -> new ToDegreesEvaluator.Factory(new ToDoubleFromIntEvaluator.Factory(field, source), source)), @@ -57,6 +66,15 @@ public class ToDegrees extends AbstractConvertFunction implements EvaluatorMappe super(source, field); } + private ToDegrees(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDouble.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDouble.java index b30162ef2334..de88281e7dbd 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDouble.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDouble.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -33,6 +36,7 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToDo import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToDouble; public class ToDouble extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToDouble", ToDouble::new); private static final Map EVALUATORS = Map.ofEntries( Map.entry(DOUBLE, (fieldEval, source) -> fieldEval), @@ -86,6 +90,15 @@ public class ToDouble extends AbstractConvertFunction { super(source, field); } + private ToDouble(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPoint.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPoint.java index 4692155fc973..51cb08137a58 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPoint.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPoint.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -26,6 +29,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToSpatial; public class ToGeoPoint extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToGeoPoint", + ToGeoPoint::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(GEO_POINT, (fieldEval, source) -> fieldEval), @@ -52,6 +60,15 @@ public class ToGeoPoint extends AbstractConvertFunction { super(source, field); } + private ToGeoPoint(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java index 93acd578f86c..00e9fb3e598f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -27,6 +30,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToSpatial; public class ToGeoShape extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToGeoShape", + ToGeoShape::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(GEO_POINT, (fieldEval, source) -> fieldEval), @@ -54,6 +62,15 @@ public class ToGeoShape extends AbstractConvertFunction { super(source, field); } + private ToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIP.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIP.java index 92467d98472c..6df85948d94e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIP.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIP.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -26,6 +29,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToIP; public class ToIP extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToIP", ToIP::new); private static final Map EVALUATORS = Map.ofEntries( Map.entry(IP, (field, source) -> field), @@ -58,6 +62,15 @@ public class ToIP extends AbstractConvertFunction { super(source, field); } + private ToIP(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToInteger.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToInteger.java index aa926eee3a55..1785160594a7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToInteger.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToInteger.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -34,6 +37,11 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToIn import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToInt; public class ToInteger extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToInteger", + ToInteger::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(INTEGER, (fieldEval, source) -> fieldEval), @@ -76,6 +84,15 @@ public class ToInteger extends AbstractConvertFunction { super(source, field); } + private ToInteger(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java index 182c1c923a96..4811051c3f48 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -34,6 +37,7 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToLo import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToLong; public class ToLong extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToLong", ToLong::new); private static final Map EVALUATORS = Map.ofEntries( Map.entry(LONG, (fieldEval, source) -> fieldEval), @@ -86,6 +90,15 @@ public class ToLong extends AbstractConvertFunction { super(source, field); } + private ToLong(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadians.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadians.java index 2fd8ae1eb0bd..a73c75a4e823 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadians.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadians.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -30,6 +33,12 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; * to radians. */ public class ToRadians extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToRadians", + ToRadians::new + ); + private static final Map EVALUATORS = Map.ofEntries( Map.entry(DOUBLE, ToRadiansEvaluator.Factory::new), Map.entry(INTEGER, (field, source) -> new ToRadiansEvaluator.Factory(new ToDoubleFromIntEvaluator.Factory(field, source), source)), @@ -56,6 +65,15 @@ public class ToRadians extends AbstractConvertFunction implements EvaluatorMappe super(source, field); } + private ToRadians(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java index 141fa067e54e..cb9eae6b5f43 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -43,6 +46,7 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLo import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.versionToString; public class ToString extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToString", ToString::new); private static final Map EVALUATORS = Map.ofEntries( Map.entry(KEYWORD, (fieldEval, source) -> fieldEval), @@ -93,6 +97,15 @@ public class ToString extends AbstractConvertFunction implements EvaluatorMapper super(source, v); } + private ToString(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLong.java index ad6e935f7d6a..bfbfcf44b394 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLong.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -18,6 +20,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -36,6 +39,11 @@ import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.longToUnsi import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToUnsignedLong; public class ToUnsignedLong extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToUnsignedLong", + ToUnsignedLong::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(UNSIGNED_LONG, (fieldEval, source) -> fieldEval), @@ -77,6 +85,15 @@ public class ToUnsignedLong extends AbstractConvertFunction { super(source, field); } + private ToUnsignedLong(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersion.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersion.java index 1941dd00837b..f6002c3c6bb1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersion.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersion.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -26,6 +29,11 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToVersion; public class ToVersion extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "ToVersion", + ToVersion::new + ); private static final Map EVALUATORS = Map.ofEntries( Map.entry(VERSION, (fieldEval, source) -> fieldEval), @@ -49,6 +57,15 @@ public class ToVersion extends AbstractConvertFunction { super(source, v); } + private ToVersion(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Map factories() { return EVALUATORS; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Abs.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Abs.java index b821b8449a5a..363b70ef5ed1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Abs.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Abs.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -19,10 +21,13 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; public class Abs extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Abs", Abs::new); + @FunctionInfo( returnType = { "double", "integer", "long", "unsigned_long" }, description = "Returns the absolute value.", @@ -39,6 +44,15 @@ public class Abs extends UnaryScalarFunction { super(source, n); } + private Abs(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Evaluator(extraName = "Double") static double process(double fieldVal) { return Math.abs(fieldVal); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java index fee52567d161..8353fe24b3dd 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -14,6 +15,7 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.function.Function; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; @@ -27,6 +29,10 @@ abstract class AbstractTrigonometricFunction extends UnaryScalarFunction { super(source, field); } + protected AbstractTrigonometricFunction(StreamInput in) throws IOException { + super(in); + } + /** * Build an evaluator for this function given the evaluator for it's input. */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Acos.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Acos.java index e3c83f2f4abc..a87fa8ad48bb 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Acos.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Acos.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Inverse cosine trigonometric function. */ public class Acos extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Acos", Acos::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Inverse_trigonometric_functions[arccosine] of `n` as an angle, expressed in radians.", @@ -38,6 +43,15 @@ public class Acos extends AbstractTrigonometricFunction { super(source, n); } + private Acos(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new AcosEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Asin.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Asin.java index bc2de0a5b511..5d8c71a461ca 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Asin.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Asin.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Inverse cosine trigonometric function. */ public class Asin extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Asin", Asin::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Inverse_trigonometric_functions[arcsine] of the input\n" @@ -39,6 +44,15 @@ public class Asin extends AbstractTrigonometricFunction { super(source, n); } + private Asin(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new AsinEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Atan.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Atan.java index d840faf6d970..d90b12dfef43 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Atan.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Atan.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Inverse cosine trigonometric function. */ public class Atan extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Atan", Atan::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Inverse_trigonometric_functions[arctangent] of the input\n" @@ -39,6 +44,15 @@ public class Atan extends AbstractTrigonometricFunction { super(source, n); } + private Atan(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new AtanEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cbrt.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cbrt.java index 43c0353de490..364e91aad8b1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cbrt.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cbrt.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -19,6 +21,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -27,6 +30,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNum import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToDouble; public class Cbrt extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Cbrt", Cbrt::new); + @FunctionInfo(returnType = "double", description = """ Returns the cube root of a number. The input can be any numeric value, the return value is always a double. Cube roots of infinities are null.""", examples = @Example(file = "math", tag = "cbrt")) @@ -41,6 +46,15 @@ public class Cbrt extends UnaryScalarFunction { super(source, n); } + private Cbrt(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public ExpressionEvaluator.Factory toEvaluator(Function toEvaluator) { var field = toEvaluator.apply(field()); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Ceil.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Ceil.java index 06f092a00e94..7d31cec0e54a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Ceil.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Ceil.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -31,6 +34,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNum *

*/ public class Ceil extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Ceil", Ceil::new); + @FunctionInfo( returnType = { "double", "integer", "long", "unsigned_long" }, description = "Round a number up to the nearest integer.", @@ -49,6 +54,15 @@ public class Ceil extends UnaryScalarFunction { super(source, n); } + private Ceil(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public ExpressionEvaluator.Factory toEvaluator(Function toEvaluator) { if (dataType().isInteger()) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java index 29387606a497..4ae134a8d6c2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Cosine trigonometric function. */ public class Cos extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Cos", Cos::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Sine_and_cosine[cosine] of an angle.", @@ -38,6 +43,15 @@ public class Cos extends AbstractTrigonometricFunction { super(source, angle); } + private Cos(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new CosEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java index 5e0a8c9b970f..0cfbc195186f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Cosine hyperbolic function. */ public class Cosh extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Cosh", Cosh::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Hyperbolic_functions[hyperbolic cosine] of an angle.", @@ -38,6 +43,15 @@ public class Cosh extends AbstractTrigonometricFunction { super(source, angle); } + private Cosh(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new CoshEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Floor.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Floor.java index 173a8ef15230..73ff0aec2b12 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Floor.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Floor.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -17,6 +19,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -31,6 +34,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNum *

*/ public class Floor extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Floor", Floor::new); + @FunctionInfo( returnType = { "double", "integer", "long", "unsigned_long" }, description = "Round a number down to the nearest integer.", @@ -51,6 +56,15 @@ public class Floor extends UnaryScalarFunction { super(source, n); } + private Floor(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public ExpressionEvaluator.Factory toEvaluator(Function toEvaluator) { if (dataType().isInteger()) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10.java index 69b7efac9b7e..ae725f6ed649 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -28,6 +31,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNum import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToDouble; public class Log10 extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Log10", Log10::new); + @FunctionInfo( returnType = "double", description = "Returns the logarithm of a value to base 10. The input can " @@ -47,6 +52,15 @@ public class Log10 extends UnaryScalarFunction { super(source, n); } + private Log10(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public ExpressionEvaluator.Factory toEvaluator(Function toEvaluator) { var field = toEvaluator.apply(field()); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Signum.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Signum.java index 7769e8c6c4a2..e78c2ce90e6c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Signum.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Signum.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -20,10 +22,13 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; public class Signum extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Signum", Signum::new); + @FunctionInfo( returnType = { "double" }, description = "Returns the sign of the given number.\n" @@ -41,6 +46,15 @@ public class Signum extends UnaryScalarFunction { super(source, n); } + private Signum(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public EvalOperator.ExpressionEvaluator.Factory toEvaluator( Function toEvaluator diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java index 2dd9520ab066..526b17fb3eb2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,14 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Sine trigonometric function. */ public class Sin extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Sin", Sin::new); @FunctionInfo( returnType = "double", @@ -39,6 +43,15 @@ public class Sin extends AbstractTrigonometricFunction { super(source, angle); } + private Sin(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new SinEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java index 274fb938f68d..f89e626955d7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Sine hyperbolic function. */ public class Sinh extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Sinh", Sinh::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Hyperbolic_functions[hyperbolic sine] of an angle.", @@ -38,6 +43,15 @@ public class Sinh extends AbstractTrigonometricFunction { super(source, angle); } + private Sinh(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new SinhEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sqrt.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sqrt.java index a27929b0b5d0..d1af693d8aa7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sqrt.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sqrt.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -19,6 +21,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -27,6 +30,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNum import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.unsignedLongToDouble; public class Sqrt extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Sqrt", Sqrt::new); + @FunctionInfo(returnType = "double", description = """ Returns the square root of a number. The input can be any numeric value, the return value is always a double. Square roots of negative numbers and infinities are null.""", examples = @Example(file = "math", tag = "sqrt")) @@ -41,6 +46,15 @@ public class Sqrt extends UnaryScalarFunction { super(source, n); } + private Sqrt(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public ExpressionEvaluator.Factory toEvaluator(Function toEvaluator) { var field = toEvaluator.apply(field()); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java index e0ae6ff5234e..85cdba0db468 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Tangent trigonometric function. */ public class Tan extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Tan", Tan::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Sine_and_cosine[Tangent] trigonometric function of an angle.", @@ -38,6 +43,15 @@ public class Tan extends AbstractTrigonometricFunction { super(source, angle); } + private Tan(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new TanEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java index 5d423eaf2dd3..0cd4051968c7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.math; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -16,12 +18,15 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import java.io.IOException; import java.util.List; /** * Tangent hyperbolic function. */ public class Tanh extends AbstractTrigonometricFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Tanh", Tanh::new); + @FunctionInfo( returnType = "double", description = "Returns the {wikipedia}/Hyperbolic_functions[Tangent] hyperbolic function of an angle.", @@ -38,6 +43,15 @@ public class Tanh extends AbstractTrigonometricFunction { super(source, angle); } + private Tanh(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected EvalOperator.ExpressionEvaluator.Factory doubleEvaluator(EvalOperator.ExpressionEvaluator.Factory field) { return new TanhEvaluator.Factory(source(), field); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java index bf0e10f817e3..7e7a024ba2c4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/package-info.java @@ -54,7 +54,7 @@ * *
  • * Find a function in this package similar to the one you are working on and copy it to build - * yours. There's some ceremony required in each function class to make it constant foldable + * yours. There's some ceremony required in each function class to make it constant foldable, * and return the right types. Take a stab at these, but don't worry too much about getting * it right. Your function might extend from one of several abstract base classes, all of * those are fine for this guide, but might have special instructions called out later. @@ -104,9 +104,21 @@ *
  • *
  • * Add your function to {@link org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry}. - * This links it into the language and {@code META FUNCTIONS}. Also add your function to - * {@link org.elasticsearch.xpack.esql.io.stream.PlanNamedTypes}. This makes your function - * serializable over the wire. Mostly you can copy existing implementations for both. + * This links it into the language and {@code META FUNCTIONS}. + *
  • + *
  • + * Register your function for serialization. We're in the process of migrating this serialization + * from an older way to the more common, {@link org.elasticsearch.common.io.stream.NamedWriteable}. + *

    + * All subclasses of {@link org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction} + * are migrated and should include a "getWriteableName", "writeTo", and a deserializing constructor. + * They should also include a {@link org.elasticsearch.common.io.stream.NamedWriteableRegistry.Entry} + * and it should be linked in {@link org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction}. + *

    + *

    + * Other functions serialized in {@link org.elasticsearch.xpack.esql.io.stream.PlanNamedTypes} + * and you should copy what's done there. + *

    *
  • *
  • * Rerun the {@code CsvTests}. They should find your function and maybe even pass. Add a diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StX.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StX.java index 2af1a353a39d..18046135933b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StX.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StX.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -35,6 +38,8 @@ import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isSpat * Alternatively it is well described in PostGIS documentation at PostGIS:ST_X. */ public class StX extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StX", StX::new); + @FunctionInfo( returnType = "double", description = "Extracts the `x` coordinate from the supplied point.\n" @@ -52,6 +57,15 @@ public class StX extends UnaryScalarFunction { super(source, field); } + private StX(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected Expression.TypeResolution resolveType() { return isSpatialPoint(field(), sourceText(), TypeResolutions.ParamOrdinal.DEFAULT); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StY.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StY.java index 266c5f986c52..bf97c3e2a354 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StY.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StY.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -35,6 +38,8 @@ import static org.elasticsearch.xpack.esql.expression.EsqlTypeResolutions.isSpat * Alternatively it is well described in PostGIS documentation at PostGIS:ST_Y. */ public class StY extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StY", StY::new); + @FunctionInfo( returnType = "double", description = "Extracts the `y` coordinate from the supplied point.\n" @@ -52,6 +57,15 @@ public class StY extends UnaryScalarFunction { super(source, field); } + private StY(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected TypeResolution resolveType() { return isSpatialPoint(field(), sourceText(), TypeResolutions.ParamOrdinal.DEFAULT); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LTrim.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LTrim.java index e7e0b69d5149..ece70da51ef1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LTrim.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LTrim.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.UnicodeUtil; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -29,6 +32,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr * Removes leading whitespaces from a string. */ public class LTrim extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "LTrim", LTrim::new); + @FunctionInfo( returnType = { "keyword", "text" }, description = "Removes leading whitespaces from a string.", @@ -45,6 +50,15 @@ public class LTrim extends UnaryScalarFunction { super(source, str); } + private LTrim(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected TypeResolution resolveType() { if (childrenResolved() == false) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java index e2beda9612b0..241eab6d5b90 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.UnicodeUtil; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -27,6 +30,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.Param import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString; public class Length extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Length", Length::new); @FunctionInfo( returnType = "integer", @@ -44,6 +48,15 @@ public class Length extends UnaryScalarFunction { super(source, field); } + private Length(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override public DataType dataType() { return DataType.INTEGER; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/RTrim.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/RTrim.java index 9edac22ca643..4c210607cfbe 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/RTrim.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/RTrim.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.UnicodeUtil; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -29,6 +32,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr * Removes trailing whitespaces from a string. */ public class RTrim extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "RTrim", RTrim::new); + @FunctionInfo( returnType = { "keyword", "text" }, description = "Removes trailing whitespaces from a string.", @@ -45,6 +50,15 @@ public class RTrim extends UnaryScalarFunction { super(source, str); } + private RTrim(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected TypeResolution resolveType() { if (childrenResolved() == false) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Trim.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Trim.java index d7d9019a7fba..36dc3d97992a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Trim.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Trim.java @@ -9,6 +9,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.UnicodeUtil; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -20,6 +22,7 @@ import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.util.List; import java.util.function.Function; @@ -29,6 +32,8 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr * Removes leading and trailing whitespaces from a string. */ public final class Trim extends UnaryScalarFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Trim", Trim::new); + @FunctionInfo( returnType = { "keyword", "text" }, description = "Removes leading and trailing whitespaces from a string.", @@ -45,6 +50,15 @@ public final class Trim extends UnaryScalarFunction { super(source, str); } + private Trim(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + @Override protected TypeResolution resolveType() { if (childrenResolved() == false) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Neg.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Neg.java index 50fb5c58e200..d1ed5579c448 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Neg.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/Neg.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; @@ -15,9 +17,9 @@ import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.Warnings; import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; +import java.io.IOException; import java.time.Duration; import java.time.Period; import java.util.List; @@ -30,12 +32,19 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.TIME_DURATION; import static org.elasticsearch.xpack.esql.type.EsqlDataTypes.isTemporalAmount; public class Neg extends UnaryScalarFunction { - - private final Warnings warnings; + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Neg", Neg::new); public Neg(Source source, Expression field) { super(source, field); - warnings = new Warnings(source); + } + + public Neg(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNameRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNameRegistry.java index d5eb5984e2e6..15368dc0fdb3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNameRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNameRegistry.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.io.stream; +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; @@ -80,8 +82,6 @@ public class PlanNameRegistry { record Entry( /** The superclass of a writeable category will be read by a reader. */ Class categoryClass, - /** The concrete class. */ - Class concreteClass, /** A name for the writeable which is unique to the categoryClass. */ String name, /** A writer for non-NamedWriteable class */ @@ -104,7 +104,16 @@ public class PlanNameRegistry { PlanWriter writer, PlanReader reader ) { - return new Entry(categoryClass, concreteClass, PlanNamedTypes.name(concreteClass), writer, reader); + return new Entry(categoryClass, PlanNamedTypes.name(concreteClass), writer, reader); + } + + static Entry of(Class categoryClass, NamedWriteableRegistry.Entry entry) { + return new Entry( + categoryClass, + entry.name, + (o, v) -> categoryClass.cast(v).writeTo(o), + in -> categoryClass.cast(entry.reader.read(in)) + ); } static Entry of( @@ -113,7 +122,7 @@ public class PlanNameRegistry { PlanWriter writer, PlanNamedReader reader ) { - return new Entry(categoryClass, concreteClass, PlanNamedTypes.name(concreteClass), writer, reader); + return new Entry(categoryClass, PlanNamedTypes.name(concreteClass), writer, reader); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java index 20d9907c61ba..795790949f66 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java @@ -12,6 +12,7 @@ import org.elasticsearch.TransportVersion; import org.elasticsearch.TransportVersions; import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.lucene.BytesRefs; @@ -26,10 +27,8 @@ import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.Literal; -import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.NamedExpression; import org.elasticsearch.xpack.esql.core.expression.Order; -import org.elasticsearch.xpack.esql.core.expression.ReferenceAttribute; import org.elasticsearch.xpack.esql.core.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.esql.core.expression.predicate.logical.And; import org.elasticsearch.xpack.esql.core.expression.predicate.logical.BinaryLogic; @@ -68,23 +67,6 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFuncti import org.elasticsearch.xpack.esql.expression.function.scalar.conditional.Case; import org.elasticsearch.xpack.esql.expression.function.scalar.conditional.Greatest; import org.elasticsearch.xpack.esql.expression.function.scalar.conditional.Least; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.FromBase64; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToBase64; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToBoolean; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianPoint; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianShape; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDatetime; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDegrees; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoPoint; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoShape; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIP; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLong; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToRadians; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToString; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToUnsignedLong; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToVersion; import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateDiff; import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateExtract; import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateFormat; @@ -93,28 +75,12 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateTrunc; import org.elasticsearch.xpack.esql.expression.function.scalar.date.Now; import org.elasticsearch.xpack.esql.expression.function.scalar.ip.CIDRMatch; import org.elasticsearch.xpack.esql.expression.function.scalar.ip.IpPrefix; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Acos; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Asin; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Atan; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Atan2; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cbrt; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Ceil; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cos; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cosh; import org.elasticsearch.xpack.esql.expression.function.scalar.math.E; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Floor; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log10; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pi; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pow; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Round; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Signum; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sin; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sinh; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sqrt; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tan; -import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tanh; import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tau; import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.AbstractMultivalueFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvAppend; @@ -137,16 +103,11 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialDi import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialIntersects; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialWithin; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StY; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Concat; import org.elasticsearch.xpack.esql.expression.function.scalar.string.EndsWith; -import org.elasticsearch.xpack.esql.expression.function.scalar.string.LTrim; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Left; -import org.elasticsearch.xpack.esql.expression.function.scalar.string.Length; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Locate; import org.elasticsearch.xpack.esql.expression.function.scalar.string.RLike; -import org.elasticsearch.xpack.esql.expression.function.scalar.string.RTrim; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Repeat; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Replace; import org.elasticsearch.xpack.esql.expression.function.scalar.string.Right; @@ -155,13 +116,11 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.StartsWith import org.elasticsearch.xpack.esql.expression.function.scalar.string.Substring; import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToLower; import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToUpper; -import org.elasticsearch.xpack.esql.expression.function.scalar.string.Trim; import org.elasticsearch.xpack.esql.expression.function.scalar.string.WildcardLike; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Div; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Mod; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Mul; -import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Neg; import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison; @@ -211,6 +170,7 @@ import org.elasticsearch.xpack.esql.plan.physical.ShowExec; import org.elasticsearch.xpack.esql.plan.physical.TopNExec; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -261,7 +221,7 @@ public final class PlanNamedTypes { * Entries have the form: category, name, serializer method, deserializer method. */ public static List namedTypeEntries() { - return List.of( + List declared = List.of( // Physical Plan Nodes of(PhysicalPlan.class, AggregateExec.class, PlanNamedTypes::writeAggregateExec, PlanNamedTypes::readAggregateExec), of(PhysicalPlan.class, DissectExec.class, PlanNamedTypes::writeDissectExec, PlanNamedTypes::readDissectExec), @@ -307,13 +267,6 @@ public final class PlanNamedTypes { of(LogicalPlan.class, OrderBy.class, PlanNamedTypes::writeOrderBy, PlanNamedTypes::readOrderBy), of(LogicalPlan.class, Project.class, PlanNamedTypes::writeProject, PlanNamedTypes::readProject), of(LogicalPlan.class, TopN.class, PlanNamedTypes::writeTopN, PlanNamedTypes::readTopN), - // Attributes - of(Expression.class, FieldAttribute.class, (o, a) -> a.writeTo(o), FieldAttribute::new), - of(Expression.class, ReferenceAttribute.class, (o, a) -> a.writeTo(o), ReferenceAttribute::new), - of(Expression.class, MetadataAttribute.class, (o, a) -> a.writeTo(o), MetadataAttribute::new), - of(Expression.class, UnsupportedAttribute.class, (o, a) -> a.writeTo(o), UnsupportedAttribute::new), - // NamedExpressions - of(Expression.class, Alias.class, (o, a) -> a.writeTo(o), Alias::new), // BinaryComparison of(EsqlBinaryComparison.class, Equals.class, PlanNamedTypes::writeBinComparison, PlanNamedTypes::readBinComparison), of(EsqlBinaryComparison.class, NotEquals.class, PlanNamedTypes::writeBinComparison, PlanNamedTypes::readBinComparison), @@ -340,46 +293,6 @@ public final class PlanNamedTypes { of(QL_UNARY_SCLR_CLS, IsNotNull.class, PlanNamedTypes::writeQLUnaryScalar, PlanNamedTypes::readQLUnaryScalar), of(QL_UNARY_SCLR_CLS, IsNull.class, PlanNamedTypes::writeQLUnaryScalar, PlanNamedTypes::readQLUnaryScalar), of(QL_UNARY_SCLR_CLS, Not.class, PlanNamedTypes::writeQLUnaryScalar, PlanNamedTypes::readQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Neg.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Abs.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Acos.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Asin.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Atan.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Cbrt.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Ceil.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Cos.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Cosh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Floor.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, FromBase64.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Length.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Log10.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, LTrim.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, RTrim.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Signum.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Sin.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Sinh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Sqrt.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, StX.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, StY.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Tan.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Tanh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToBase64.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToBoolean.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToCartesianPoint.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToDatetime.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToDegrees.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToDouble.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToGeoShape.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToCartesianShape.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToGeoPoint.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToIP.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToInteger.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToLong.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToRadians.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToString.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToUnsignedLong.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, ToVersion.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), - of(ESQL_UNARY_SCLR_CLS, Trim.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar), // ScalarFunction of(ScalarFunction.class, Atan2.class, PlanNamedTypes::writeAtan2, PlanNamedTypes::readAtan2), of(ScalarFunction.class, Case.class, PlanNamedTypes::writeVararg, PlanNamedTypes::readVarag), @@ -455,6 +368,18 @@ public final class PlanNamedTypes { of(Expression.class, Literal.class, PlanNamedTypes::writeLiteral, PlanNamedTypes::readLiteral), of(Expression.class, Order.class, PlanNamedTypes::writeOrder, PlanNamedTypes::readOrder) ); + List entries = new ArrayList<>(declared); + + // From NamedWriteables + for (NamedWriteableRegistry.Entry e : UnaryScalarFunction.getNamedWriteables()) { + entries.add(of(ESQL_UNARY_SCLR_CLS, e)); + } + for (NamedWriteableRegistry.Entry e : NamedExpression.getNamedWriteables()) { + entries.add(of(Expression.class, e)); + } + entries.add(of(Expression.class, UnsupportedAttribute.ENTRY)); + + return entries; } // -- physical plan nodes @@ -1172,64 +1097,6 @@ public final class PlanNamedTypes { out.writeExpression(binaryLogic.right()); } - // -- UnaryScalarFunction - - static final Map> ESQL_UNARY_SCALAR_CTRS = Map.ofEntries( - entry(name(Abs.class), Abs::new), - entry(name(Acos.class), Acos::new), - entry(name(Asin.class), Asin::new), - entry(name(Atan.class), Atan::new), - entry(name(Cbrt.class), Cbrt::new), - entry(name(Ceil.class), Ceil::new), - entry(name(Cos.class), Cos::new), - entry(name(Cosh.class), Cosh::new), - entry(name(Floor.class), Floor::new), - entry(name(FromBase64.class), FromBase64::new), - entry(name(Length.class), Length::new), - entry(name(Log10.class), Log10::new), - entry(name(LTrim.class), LTrim::new), - entry(name(RTrim.class), RTrim::new), - entry(name(Neg.class), Neg::new), - entry(name(Signum.class), Signum::new), - entry(name(Sin.class), Sin::new), - entry(name(Sinh.class), Sinh::new), - entry(name(Sqrt.class), Sqrt::new), - entry(name(StX.class), StX::new), - entry(name(StY.class), StY::new), - entry(name(Tan.class), Tan::new), - entry(name(Tanh.class), Tanh::new), - entry(name(ToBase64.class), ToBase64::new), - entry(name(ToBoolean.class), ToBoolean::new), - entry(name(ToCartesianPoint.class), ToCartesianPoint::new), - entry(name(ToDatetime.class), ToDatetime::new), - entry(name(ToDegrees.class), ToDegrees::new), - entry(name(ToDouble.class), ToDouble::new), - entry(name(ToGeoShape.class), ToGeoShape::new), - entry(name(ToCartesianShape.class), ToCartesianShape::new), - entry(name(ToGeoPoint.class), ToGeoPoint::new), - entry(name(ToIP.class), ToIP::new), - entry(name(ToInteger.class), ToInteger::new), - entry(name(ToLong.class), ToLong::new), - entry(name(ToRadians.class), ToRadians::new), - entry(name(ToString.class), ToString::new), - entry(name(ToUnsignedLong.class), ToUnsignedLong::new), - entry(name(ToVersion.class), ToVersion::new), - entry(name(Trim.class), Trim::new) - ); - - static UnaryScalarFunction readESQLUnaryScalar(PlanStreamInput in, String name) throws IOException { - var ctr = ESQL_UNARY_SCALAR_CTRS.get(name); - if (ctr == null) { - throw new IOException("Constructor for ESQLUnaryScalar not found for name:" + name); - } - return ctr.apply(Source.readFrom(in), in.readExpression()); - } - - static void writeESQLUnaryScalar(PlanStreamOutput out, UnaryScalarFunction function) throws IOException { - function.source().writeTo(out); - out.writeExpression(function.field()); - } - static final Map> NO_ARG_SCALAR_CTRS = Map.ofEntries( entry(name(E.class), E::new), entry(name(Pi.class), Pi::new), diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java index 4fdc0bdab5ad..228ed6c5b4b3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java @@ -197,7 +197,7 @@ public class EsqlPlugin extends Plugin implements ActionPlugin { entries.addAll(Attribute.getNamedWriteables()); entries.add(UnsupportedAttribute.ENTRY); // TODO combine with above once these are in the same project entries.addAll(NamedExpression.getNamedWriteables()); - entries.add(UnsupportedAttribute.NAMED_EXPRESSION_ENTRY); + entries.add(UnsupportedAttribute.NAMED_EXPRESSION_ENTRY); // TODO combine with above once these are in the same project return entries; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractExpressionSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractExpressionSerializationTests.java new file mode 100644 index 000000000000..a5ce5e004b19 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractExpressionSerializationTests.java @@ -0,0 +1,90 @@ +/* + * 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.expression; + +import org.elasticsearch.TransportVersion; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.test.AbstractWireTestCase; +import org.elasticsearch.xpack.esql.core.expression.Attribute; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.NamedExpression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.EsField; +import org.elasticsearch.xpack.esql.expression.function.ReferenceAttributeTests; +import org.elasticsearch.xpack.esql.expression.function.UnsupportedAttribute; +import org.elasticsearch.xpack.esql.io.stream.PlanNameRegistry; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; +import org.elasticsearch.xpack.esql.session.EsqlConfiguration; +import org.elasticsearch.xpack.esql.session.EsqlConfigurationSerializationTests; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.hamcrest.Matchers.equalTo; + +public abstract class AbstractExpressionSerializationTests extends AbstractWireTestCase { + public static Source randomSource() { + int lineNumber = between(0, EXAMPLE_QUERY.length - 1); + int offset = between(0, EXAMPLE_QUERY[lineNumber].length() - 2); + int length = between(1, EXAMPLE_QUERY[lineNumber].length() - offset - 1); + String text = EXAMPLE_QUERY[lineNumber].substring(offset, offset + length); + return new Source(lineNumber + 1, offset, text); + } + + public static Expression randomChild() { + return ReferenceAttributeTests.randomReferenceAttribute(); + } + + @Override + protected final T copyInstance(T instance, TransportVersion version) throws IOException { + EsqlConfiguration config = EsqlConfigurationSerializationTests.randomConfiguration( + Arrays.stream(EXAMPLE_QUERY).collect(Collectors.joining("\n")), + Map.of() + ); + return copyInstance( + instance, + getNamedWriteableRegistry(), + (out, v) -> new PlanStreamOutput(out, new PlanNameRegistry(), config).writeNamedWriteable(v), + in -> { + PlanStreamInput pin = new PlanStreamInput(in, new PlanNameRegistry(), in.namedWriteableRegistry(), config); + @SuppressWarnings("unchecked") + T deser = (T) pin.readNamedWriteable(Expression.class); + assertThat(deser.source(), equalTo(instance.source())); + return deser; + }, + version + ); + } + + protected abstract List getNamedWriteables(); + + @Override + protected final NamedWriteableRegistry getNamedWriteableRegistry() { + List entries = new ArrayList<>(NamedExpression.getNamedWriteables()); + entries.addAll(Attribute.getNamedWriteables()); + entries.add(UnsupportedAttribute.ENTRY); + entries.addAll(EsField.getNamedWriteables()); + entries.addAll(getNamedWriteables()); + return new NamedWriteableRegistry(entries); + } + + private static final String[] EXAMPLE_QUERY = new String[] { + "I am the very model of a modern Major-Gineral,", + "I've information vegetable, animal, and mineral,", + "I know the kings of England, and I quote the fights historical", + "From Marathon to Waterloo, in order categorical;", + "I'm very well acquainted, too, with matters mathematical,", + "I understand equations, both the simple and quadratical,", + "About binomial theorem I'm teeming with a lot o' news,", + "With many cheerful facts about the square of the hypotenuse." }; +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractUnaryScalarSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractUnaryScalarSerializationTests.java new file mode 100644 index 000000000000..d8290966acbd --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/AbstractUnaryScalarSerializationTests.java @@ -0,0 +1,36 @@ +/* + * 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.expression; + +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction; + +import java.io.IOException; +import java.util.List; + +public abstract class AbstractUnaryScalarSerializationTests extends AbstractExpressionSerializationTests { + protected abstract T create(Source source, Expression child); + + @Override + protected final T createTestInstance() { + return create(randomSource(), randomChild()); + } + + @Override + protected final T mutateInstance(T instance) throws IOException { + Expression child = randomValueOtherThan(instance.field(), AbstractExpressionSerializationTests::randomChild); + return create(instance.source(), child); + } + + @Override + protected List getNamedWriteables() { + return UnaryScalarFunction.getNamedWriteables(); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64SerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64SerializationTests.java new file mode 100644 index 000000000000..eee637610ffd --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/FromBase64SerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class FromBase64SerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected FromBase64 create(Source source, Expression child) { + return new FromBase64(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64SerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64SerializationTests.java new file mode 100644 index 000000000000..0eebe0d74c5b --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBase64SerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToBase64SerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToBase64 create(Source source, Expression child) { + return new ToBase64(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBooleanSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBooleanSerializationTests.java new file mode 100644 index 000000000000..0f94eb46110e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToBooleanSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToBooleanSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToBoolean create(Source source, Expression child) { + return new ToBoolean(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPointSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPointSerializationTests.java new file mode 100644 index 000000000000..601320f9fbda --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianPointSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToCartesianPointSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToCartesianPoint create(Source source, Expression child) { + return new ToCartesianPoint(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShapeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShapeSerializationTests.java new file mode 100644 index 000000000000..96762ca28040 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToCartesianShapeSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToCartesianShapeSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToCartesianShape create(Source source, Expression child) { + return new ToCartesianShape(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetimeSerializationTests.java new file mode 100644 index 000000000000..935269ee76f4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDatetimeSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToDatetimeSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToDatetime create(Source source, Expression child) { + return new ToDatetime(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegreesSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegreesSerializationTests.java new file mode 100644 index 000000000000..fd0f1dba4bf6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDegreesSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToDegreesSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToDegrees create(Source source, Expression child) { + return new ToDegrees(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDoubleSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDoubleSerializationTests.java new file mode 100644 index 000000000000..c2eef3b26dbb --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDoubleSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToDoubleSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToDouble create(Source source, Expression child) { + return new ToDouble(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPointSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPointSerializationTests.java new file mode 100644 index 000000000000..9e210a887a17 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoPointSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeoPointSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeoPoint create(Source source, Expression child) { + return new ToGeoPoint(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeSerializationTests.java new file mode 100644 index 000000000000..71e4bc335a90 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeoShapeSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeoShape create(Source source, Expression child) { + return new ToGeoShape(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIPSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIPSerializationTests.java new file mode 100644 index 000000000000..76657639a583 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIPSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToIPSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToIP create(Source source, Expression child) { + return new ToIP(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSerializationTests.java new file mode 100644 index 000000000000..3c8c47414b28 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToIntegerSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToInteger create(Source source, Expression child) { + return new ToInteger(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSerializationTests.java new file mode 100644 index 000000000000..7acba8c04171 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToLongSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToLong create(Source source, Expression child) { + return new ToLong(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadiansSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadiansSerializationTests.java new file mode 100644 index 000000000000..396feb6d13a9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToRadiansSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToRadiansSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToRadians create(Source source, Expression child) { + return new ToRadians(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringSerializationTests.java new file mode 100644 index 000000000000..08bfa106cbd9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToStringSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToString create(Source source, Expression child) { + return new ToString(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLongSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLongSerializationTests.java new file mode 100644 index 000000000000..3e58e8d4f4ad --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToUnsignedLongSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToUnsignedLongSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToUnsignedLong create(Source source, Expression child) { + return new ToUnsignedLong(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersionSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersionSerializationTests.java new file mode 100644 index 000000000000..62548212d843 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToVersionSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToVersionSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToVersion create(Source source, Expression child) { + return new ToVersion(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbsSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbsSerializationTests.java new file mode 100644 index 000000000000..fd447c34d3fa --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbsSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class AbsSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Abs create(Source source, Expression child) { + return new Abs(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AcosSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AcosSerializationTests.java new file mode 100644 index 000000000000..d980fa95c3b9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AcosSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class AcosSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Acos create(Source source, Expression child) { + return new Acos(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AsinSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AsinSerializationTests.java new file mode 100644 index 000000000000..09000388c553 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AsinSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class AsinSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Asin create(Source source, Expression child) { + return new Asin(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AtanSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AtanSerializationTests.java new file mode 100644 index 000000000000..2176f06c82a1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AtanSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class AtanSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Atan create(Source source, Expression child) { + return new Atan(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CbrtSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CbrtSerializationTests.java new file mode 100644 index 000000000000..294dd1d378d2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CbrtSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class CbrtSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Cbrt create(Source source, Expression child) { + return new Cbrt(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CeilSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CeilSerializationTests.java new file mode 100644 index 000000000000..7105a44ed9a0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CeilSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class CeilSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Ceil create(Source source, Expression child) { + return new Ceil(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosSerializationTests.java new file mode 100644 index 000000000000..0be0c411ebea --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class CosSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Cos create(Source source, Expression child) { + return new Cos(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshSerializationTests.java new file mode 100644 index 000000000000..cb8ee99869c2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class CoshSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Cosh create(Source source, Expression child) { + return new Cosh(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/FloorSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/FloorSerializationTests.java new file mode 100644 index 000000000000..48fdd68e8690 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/FloorSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class FloorSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Floor create(Source source, Expression child) { + return new Floor(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10SerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10SerializationTests.java new file mode 100644 index 000000000000..2b79bbeb8a9c --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Log10SerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class Log10SerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Log10 create(Source source, Expression child) { + return new Log10(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinSerializationTests.java new file mode 100644 index 000000000000..c9118fceaf5f --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class SinSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Sin create(Source source, Expression child) { + return new Sin(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhSerializationTests.java new file mode 100644 index 000000000000..c87e41ef3fbb --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class SinhSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Sinh create(Source source, Expression child) { + return new Sinh(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SqrtSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SqrtSerializationTests.java new file mode 100644 index 000000000000..526f50eaa4d2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SqrtSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class SqrtSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Sqrt create(Source source, Expression child) { + return new Sqrt(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanSerializationTests.java new file mode 100644 index 000000000000..9c1a0a9f514c --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class TanSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Tan create(Source source, Expression child) { + return new Tan(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhSerializationTests.java new file mode 100644 index 000000000000..3899ad34851e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.function.scalar.math; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class TanhSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Tanh create(Source source, Expression child) { + return new Tanh(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/NegSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/NegSerializationTests.java new file mode 100644 index 000000000000..241958f12d69 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/arithmetic/NegSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class NegSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected Neg create(Source source, Expression child) { + return new Neg(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypesTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypesTests.java index b45fcd272439..2278be659c53 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypesTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypesTests.java @@ -194,7 +194,7 @@ public class PlanNamedTypesTests extends ESTestCase { public void testFunctionEntries() { var serializableFunctions = PlanNamedTypes.namedTypeEntries() .stream() - .filter(e -> Function.class.isAssignableFrom(e.concreteClass())) + .filter(e -> Function.class.isAssignableFrom(e.categoryClass())) .map(PlanNameRegistry.Entry::name) .sorted() .toList(); From bf7108752ec8f7b71e843338a41136828fb4b6e7 Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Tue, 11 Jun 2024 23:14:44 +0200 Subject: [PATCH 21/34] Do not auto publish build scans if server is not configured (#109549) --- .../src/main/groovy/elasticsearch.build-scan.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build-tools-internal/src/main/groovy/elasticsearch.build-scan.gradle b/build-tools-internal/src/main/groovy/elasticsearch.build-scan.gradle index f0a7b1a6d0b1..c6930c2263ec 100644 --- a/build-tools-internal/src/main/groovy/elasticsearch.build-scan.gradle +++ b/build-tools-internal/src/main/groovy/elasticsearch.build-scan.gradle @@ -26,6 +26,10 @@ develocity { if (jenkinsUrl?.host?.endsWith('elastic.co') || jenkinsUrl?.host?.endsWith('elastic.dev') || System.getenv('BUILDKITE') == 'true') { publishing.onlyIf { true } server = 'https://gradle-enterprise.elastic.co' + } else { + publishing.onlyIf { + server.isPresent(); + } } From 429b539e5cb5f59a132258e0ed82600836569846 Mon Sep 17 00:00:00 2001 From: Dianna Hohensee Date: Tue, 11 Jun 2024 19:41:09 -0400 Subject: [PATCH 22/34] Document backwards compatibility in arch guide (#109589) Transferring our slack conversation to a more widely consumable format. --- docs/internal/GeneralArchitectureGuide.md | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/internal/GeneralArchitectureGuide.md b/docs/internal/GeneralArchitectureGuide.md index a2dadb70bf97..b4f32d73f165 100644 --- a/docs/internal/GeneralArchitectureGuide.md +++ b/docs/internal/GeneralArchitectureGuide.md @@ -68,6 +68,52 @@ state must ever be reloaded from persisted state. ## Deprecations +## Backwards Compatibility + +major releases are mostly about breaking compatibility and dropping deprecated functionality. + +Elasticsearch versions are composed of three pieces of information: the major version, the minor version, and the patch version, +in that order (major.minor.patch). Patch releases are typically bug fixes; minor releases contain improvements / new features; +and major releases essentially break compatibility and enable removal of deprecated functionality. As an example, each of 8.0.0, +8.3.0 and 8.3.1 specifies an exact release version. They all have the same major version (8) and the last two have the same minor +version (8.3). Multiversion compatibility within a cluster, or backwards compatibility with older version nodes, is guaranteed +across specific versions. + +### Transport Layer Backwards Compatibility + +Elasticsearch nodes can communicate over the network with all node versions within the same major release. All versions within +one major version X are also compatible with the last minor version releases of the previous major version, i.e. (X-1).last. +More concretely, all 8.x.x version nodes can communicate with all 7.17.x version nodes. + +### Index Format Backwards Compatibility + +Index data format backwards compatibility is guaranteed with all versions of the previous major release. All 8.x.x version nodes, +for example, can read index data written by any 7.x.x version node. 9.x.x versions, however, will not be able to read 7.x.x format +data files. + +Elasticsearch does not have an upgrade process to convert from older to newer index data formats. The user is expected to run +`reindex` on any remaining untouched data from a previous version upgrade before upgrading to the next version. There is a good +chance that older version index data will age out and be deleted before the user does the next upgrade, but `reindex` can be used +if that is not the case. + +### Snapshot Backwards Compatibility + +Snapshots taken by a cluster of version X cannot be read by a cluster running older version nodes. However, snapshots taken by an +older version cluster can continue to be read from and written to by newer version clusters: this compatibility goes back many +major versions. If a newer version cluster writes to a snapshot repository containing snapshots from an older version, then it +will do so in a way that leaves the repository format (metadata and file layout) readable by those older versions. + +Restoring indexes that have different and no longer supported data formats can be tricky: see the +[public snapshot compatibility docs][] for details. + +[public snapshot compatibility docs]: https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html#snapshot-index-compatibility + +### Upgrade + +See the [public upgrade docs][] for the upgrade process. + +[public upgrade docs]: https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html + ## Plugins (what warrants a plugin?) From 696191d1c746d22511d88a71329e1c3abf98bbbf Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Wed, 12 Jun 2024 04:06:41 +0200 Subject: [PATCH 23/34] Fix testMapperDynamicIndexSetting() failures (#109574) Currently these tests run against any old cluster older than 8.0.0, but the fix that allowed `index.mapper.dynamic` to exist is only available in 7.17.22. Adjust these tests to only run if old cluster is after version 7.17.21 and before 8.0.0 --- .../upgrades/UpgradeWithOldIndexSettingsIT.java | 5 +++-- .../upgrades/UpgradeWithOldIndexSettingsIT.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java index 95178429317b..3a2200f15276 100644 --- a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java @@ -50,8 +50,9 @@ public class UpgradeWithOldIndexSettingsIT extends ParameterizedFullClusterResta public void testMapperDynamicIndexSetting() throws IOException { assumeTrue( - "Setting deprecated in 6.x, but remained in 7.x and is no longer defined in 8.x", - getOldClusterTestVersion().before("8.0.0") + "Setting deprecated in 6.x, but was disallowed/removed incorrectly in some 7.x versions and can only be set safely in 7.17.22. " + + "Setting can't be used in 8.x ", + getOldClusterTestVersion().before("8.0.0") && getOldClusterTestVersion().after("7.17.21") ); String indexName = "my-index"; if (isRunningAgainstOldCluster()) { diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java index ba873ef6bbd7..ae75069fa564 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java @@ -106,8 +106,9 @@ public class UpgradeWithOldIndexSettingsIT extends AbstractRollingUpgradeTestCas public void testMapperDynamicIndexSetting() throws IOException { assumeTrue( - "Setting deprecated in 6.x, but remained in 7.x and is no longer defined in 8.x", - getOldClusterTestVersion().before("8.0.0") + "Setting deprecated in 6.x, but was disallowed/removed incorrectly in some 7.x versions and can only be set safely in 7.17.22. " + + "Setting can't be used in 8.x ", + getOldClusterTestVersion().before("8.0.0") && getOldClusterTestVersion().after("7.17.21") ); String indexName = "my-index"; if (isOldCluster()) { From 75617523e3ee62a051c086e9e0d0e1502ce5bf93 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 12 Jun 2024 13:24:26 +1000 Subject: [PATCH 24/34] [Test] Force close of HTTP response stream (#109558) In JDK23 the `HttpServer` requires that http response be explicitly closed (even if there is no response body) Resolves: #109452 --- .../xpack/security/authc/saml/SamlServiceProviderMetadataIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java b/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java index 383598c804f7..9d2168267bb8 100644 --- a/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java +++ b/x-pack/plugin/security/qa/saml-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/saml/SamlServiceProviderMetadataIT.java @@ -144,6 +144,7 @@ public class SamlServiceProviderMetadataIT extends ESRestTestCase { } else { if (randomBoolean()) { http.sendResponseHeaders(randomFrom(404, 401, 403, 500), 0); + http.getResponseBody().close(); } else { sendXmlContent("not valid xml", http); } From b99b5d5f253bc0f91783aa52f79d23443a8205ce Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 12 Jun 2024 06:40:00 +0100 Subject: [PATCH 25/34] Remove unused seek-tracking plugin (#109600) This was used for some performance investigations but is not currently needed, and would need updating in order to complete #100878. Instead, this commit removes it. --- .../internal/RestrictedBuildApiService.java | 1 - .../seek-tracking-directory/build.gradle | 14 - .../test/seektracker/SeekTrackerPluginIT.java | 55 ---- .../test/seektracker/IndexSeekTracker.java | 51 ---- .../test/seektracker/NodeSeekStats.java | 52 ---- .../test/seektracker/RestSeekStatsAction.java | 41 --- .../test/seektracker/SeekStatsRequest.java | 42 --- .../test/seektracker/SeekStatsResponse.java | 69 ----- .../test/seektracker/SeekStatsService.java | 30 -- .../test/seektracker/SeekTrackerPlugin.java | 100 ------- .../SeekTrackingDirectoryWrapper.java | 269 ------------------ .../test/seektracker/ShardSeekStats.java | 36 --- .../seektracker/TransportSeekStatsAction.java | 83 ------ 13 files changed, 843 deletions(-) delete mode 100644 test/external-modules/seek-tracking-directory/build.gradle delete mode 100644 test/external-modules/seek-tracking-directory/src/internalClusterTest/java/org/elasticsearch/test/seektracker/SeekTrackerPluginIT.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/IndexSeekTracker.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/NodeSeekStats.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/RestSeekStatsAction.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsRequest.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsResponse.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsService.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackerPlugin.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackingDirectoryWrapper.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/ShardSeekStats.java delete mode 100644 test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/TransportSeekStatsAction.java diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java index 23afcab7bec7..9cc98e79183c 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java @@ -71,7 +71,6 @@ public abstract class RestrictedBuildApiService implements BuildService> nodePlugins() { - return List.of(SeekTrackerPlugin.class); - } - - @Override - protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal, otherSettings)) - .put(SeekTrackerPlugin.SEEK_TRACKING_ENABLED.getKey(), "true") - .build(); - } - - public void testSeekTrackerPlugin() throws InterruptedException { - - assertAcked(indicesAdmin().prepareCreate("index")); - List docs = new ArrayList<>(); - for (int i = 0; i < 100; i++) { - docs.add(prepareIndex("index").setSource("field", "term" + i % 5)); - } - indexRandom(true, docs); - - prepareSearch("index").setQuery(QueryBuilders.termQuery("field", "term2")).get().decRef(); - - SeekStatsResponse response = client().execute(SeekTrackerPlugin.SEEK_STATS_ACTION, new SeekStatsRequest("index")).actionGet(); - List shardSeekStats = response.getSeekStats().get("index"); - assertThat(shardSeekStats.size(), greaterThan(0)); - } - -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/IndexSeekTracker.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/IndexSeekTracker.java deleted file mode 100644 index 2cb3fa4bbe6a..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/IndexSeekTracker.java +++ /dev/null @@ -1,51 +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.test.seektracker; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.LongAdder; - -public class IndexSeekTracker { - - private final String index; - private final Map> seeks = new HashMap<>(); - - public IndexSeekTracker(String index) { - this.index = index; - } - - public void track(String shard) { - seeks.computeIfAbsent(shard, k -> new ConcurrentHashMap<>()); // increment can be called by multiple threads - } - - public void increment(String shard, String file) { - seeks.get(shard).computeIfAbsent(file, s -> new LongAdder()).increment(); - } - - public List getSeeks() { - List values = new ArrayList<>(); - seeks.forEach((k, v) -> values.add(getSeeksForShard(k))); - return values; - } - - private ShardSeekStats getSeeksForShard(String shard) { - Map seeksPerFile = new HashMap<>(); - seeks.get(shard).forEach((name, adder) -> seeksPerFile.put(name, adder.longValue())); - return new ShardSeekStats(shard, seeksPerFile); - } - - @Override - public String toString() { - return "seeks for " + index + ": " + seeks; - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/NodeSeekStats.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/NodeSeekStats.java deleted file mode 100644 index 8b2d95c3cf57..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/NodeSeekStats.java +++ /dev/null @@ -1,52 +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.test.seektracker; - -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.xcontent.ToXContent; -import org.elasticsearch.xcontent.ToXContentFragment; -import org.elasticsearch.xcontent.XContentBuilder; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -public class NodeSeekStats extends BaseNodeResponse implements ToXContentFragment { - - private final Map> seeks; - - public NodeSeekStats(DiscoveryNode node, Map> seeks) { - super(node); - this.seeks = seeks; - } - - public NodeSeekStats(StreamInput in) throws IOException { - super(in); - this.seeks = in.readMap(s -> s.readCollectionAsList(ShardSeekStats::new)); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeMap(seeks, StreamOutput::writeCollection); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { - builder.mapContents(seeks); - return builder; - } - - public Map> getSeekStats() { - return seeks; - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/RestSeekStatsAction.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/RestSeekStatsAction.java deleted file mode 100644 index 8695a08ce06a..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/RestSeekStatsAction.java +++ /dev/null @@ -1,41 +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.test.seektracker; - -import org.elasticsearch.client.internal.node.NodeClient; -import org.elasticsearch.common.Strings; -import org.elasticsearch.rest.BaseRestHandler; -import org.elasticsearch.rest.RestHandler; -import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.rest.action.RestToXContentListener; - -import java.util.List; - -public class RestSeekStatsAction extends BaseRestHandler { - - @Override - public String getName() { - return "seek_stats_action"; - } - - @Override - public List routes() { - return List.of( - new RestHandler.Route(RestRequest.Method.GET, "/_seek_stats"), - new RestHandler.Route(RestRequest.Method.GET, "/{index}/_seek_stats") - ); - } - - @Override - protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) { - String[] indices = request.paramAsStringArray("index", Strings.EMPTY_ARRAY); - SeekStatsRequest seekStatsRequest = new SeekStatsRequest(indices); - return channel -> client.execute(SeekTrackerPlugin.SEEK_STATS_ACTION, seekStatsRequest, new RestToXContentListener<>(channel)); - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsRequest.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsRequest.java deleted file mode 100644 index 86dc35cc3cd4..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsRequest.java +++ /dev/null @@ -1,42 +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.test.seektracker; - -import org.elasticsearch.action.support.nodes.BaseNodesRequest; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; - -import java.io.IOException; - -public class SeekStatsRequest extends BaseNodesRequest { - - private final String[] indices; - - public SeekStatsRequest(String... indices) { - super(Strings.EMPTY_ARRAY); - this.indices = indices; - } - - public SeekStatsRequest(StreamInput in) throws IOException { - super(in); - this.indices = in.readStringArray(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeStringArray(indices); - } - - public String[] getIndices() { - return indices; - } - -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsResponse.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsResponse.java deleted file mode 100644 index 27c28345091e..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsResponse.java +++ /dev/null @@ -1,69 +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.test.seektracker; - -import org.elasticsearch.action.FailedNodeException; -import org.elasticsearch.action.support.TransportAction; -import org.elasticsearch.action.support.nodes.BaseNodesResponse; -import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.xcontent.ToXContent; -import org.elasticsearch.xcontent.ToXContentObject; -import org.elasticsearch.xcontent.XContentBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SeekStatsResponse extends BaseNodesResponse implements ToXContentObject { - - public SeekStatsResponse(ClusterName clusterName, List seekStats, List failures) { - super(clusterName, seekStats, failures); - } - - @Override - protected List readNodesFrom(StreamInput in) { - return TransportAction.localOnly(); - } - - @Override - protected void writeNodesTo(StreamOutput out, List nodes) { - TransportAction.localOnly(); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { - builder.startObject(); - for (NodeSeekStats seekStats : getNodes()) { - builder.startObject(seekStats.getNode().getId()); - seekStats.toXContent(builder, params); - builder.endObject(); - } - builder.endObject(); - return builder; - } - - public Map> getSeekStats() { - Map> combined = new HashMap<>(); - for (NodeSeekStats nodeSeekStats : getNodes()) { - nodeSeekStats.getSeekStats() - .forEach((index, shardSeekStats) -> combined.computeIfAbsent(index, k -> new ArrayList<>()).addAll(shardSeekStats)); - } - return combined; - } - - @Override - public String toString() { - return Strings.toString(this); - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsService.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsService.java deleted file mode 100644 index d98d87ab87ff..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekStatsService.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 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.test.seektracker; - -import java.util.HashMap; -import java.util.Map; - -public class SeekStatsService { - - private final Map seeks = new HashMap<>(); - - public IndexSeekTracker registerIndex(String index) { - return seeks.computeIfAbsent(index, IndexSeekTracker::new); - } - - public Map getSeekStats() { - return seeks; - } - - public IndexSeekTracker getSeekStats(String index) { - return seeks.get(index); - } - -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackerPlugin.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackerPlugin.java deleted file mode 100644 index 54ef53b8969e..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackerPlugin.java +++ /dev/null @@ -1,100 +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.test.seektracker; - -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.action.ActionType; -import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.cluster.node.DiscoveryNodes; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.settings.ClusterSettings; -import org.elasticsearch.common.settings.IndexScopedSettings; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.settings.SettingsFilter; -import org.elasticsearch.features.NodeFeature; -import org.elasticsearch.index.IndexModule; -import org.elasticsearch.plugins.ActionPlugin; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.rest.RestHandler; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import java.util.function.Supplier; - -public class SeekTrackerPlugin extends Plugin implements ActionPlugin { - - /** Setting for enabling or disabling seek tracking. Defaults to false. */ - public static final Setting SEEK_TRACKING_ENABLED = Setting.boolSetting( - "seektracker.enabled", - false, - Setting.Property.NodeScope - ); - - public static final ActionType SEEK_STATS_ACTION = new ActionType<>("cluster:monitor/seek_stats"); - - private final SeekStatsService seekStatsService = new SeekStatsService(); - private final boolean enabled; - - public SeekTrackerPlugin(Settings settings) { - this.enabled = SEEK_TRACKING_ENABLED.get(settings); - } - - @Override - public List> getSettings() { - return List.of(SEEK_TRACKING_ENABLED); - } - - @Override - public Collection createComponents(PluginServices services) { - return Collections.singletonList(seekStatsService); - } - - // seeks per index/shard/file - - @Override - public void onIndexModule(IndexModule indexModule) { - if (enabled) { - IndexSeekTracker seekTracker = seekStatsService.registerIndex(indexModule.getIndex().getName()); - indexModule.setDirectoryWrapper(new SeekTrackingDirectoryWrapper(seekTracker)); - } - } - - @Override - public List getRestHandlers( - Settings settings, - NamedWriteableRegistry namedWriteableRegistry, - RestController restController, - ClusterSettings clusterSettings, - IndexScopedSettings indexScopedSettings, - SettingsFilter settingsFilter, - IndexNameExpressionResolver indexNameExpressionResolver, - Supplier nodesInCluster, - Predicate clusterSupportsFeature - ) { - if (enabled) { - return Collections.singletonList(new RestSeekStatsAction()); - } else { - return Collections.emptyList(); - } - } - - @Override - public List> getActions() { - if (enabled) { - return Collections.singletonList(new ActionHandler<>(SEEK_STATS_ACTION, TransportSeekStatsAction.class)); - } else { - return Collections.emptyList(); - } - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackingDirectoryWrapper.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackingDirectoryWrapper.java deleted file mode 100644 index 9b3d31022c58..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/SeekTrackingDirectoryWrapper.java +++ /dev/null @@ -1,269 +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.test.seektracker; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.FilterDirectory; -import org.apache.lucene.store.IOContext; -import org.apache.lucene.store.IndexInput; -import org.apache.lucene.store.RandomAccessInput; -import org.elasticsearch.cluster.routing.ShardRouting; -import org.elasticsearch.index.IndexModule; - -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -public class SeekTrackingDirectoryWrapper implements IndexModule.DirectoryWrapper { - - private final IndexSeekTracker seekTracker; - - public SeekTrackingDirectoryWrapper(IndexSeekTracker seekTracker) { - this.seekTracker = seekTracker; - } - - @Override - public Directory wrap(Directory directory, ShardRouting shardRouting) { - seekTracker.track(shardRouting.shardId().toString()); - return new FilterDirectory(directory) { - @Override - public IndexInput openInput(String name, IOContext context) throws IOException { - IndexInput input = super.openInput(name, context); - if (input instanceof RandomAccessInput) { - return new RandomAccessSeekCountingIndexInput(input, shardRouting.shardId().toString(), name); - } - return wrapIndexInput(shardRouting.shardId().toString(), name, input); - } - }; - } - - private IndexInput wrapIndexInput(String directory, String name, IndexInput in) { - return new SeekCountingIndexInput(in, directory, name); - } - - class RandomAccessSeekCountingIndexInput extends SeekCountingIndexInput implements RandomAccessInput { - - private final RandomAccessInput randomAccessInput; - - RandomAccessSeekCountingIndexInput(IndexInput in, String directory, String name) { - super(in, directory, name); - randomAccessInput = (RandomAccessInput) unwrap(in); - } - - @Override - public IndexInput clone() { - return new RandomAccessSeekCountingIndexInput(super.clone(), directory, name); - } - - @Override - public byte readByte(long pos) throws IOException { - return randomAccessInput.readByte(pos); - } - - @Override - public short readShort(long pos) throws IOException { - return randomAccessInput.readShort(pos); - } - - @Override - public int readInt(long pos) throws IOException { - return randomAccessInput.readInt(pos); - } - - @Override - public long readLong(long pos) throws IOException { - return randomAccessInput.readLong(pos); - } - } - - class SeekCountingIndexInput extends IndexInput { - - public static IndexInput unwrap(IndexInput input) { - while (input instanceof SeekCountingIndexInput) { - input = ((SeekCountingIndexInput) input).in; - } - return input; - } - - final IndexInput in; - final String directory; - final String name; - - SeekCountingIndexInput(IndexInput in, String directory, String name) { - super(unwrap(in).toString() + "[seek_tracked]"); - this.in = unwrap(in); - this.directory = directory; - this.name = name; - } - - @Override - public IndexInput clone() { - return new SeekCountingIndexInput(in.clone(), directory, name); - } - - @Override - public void close() throws IOException { - in.close(); - } - - @Override - public long getFilePointer() { - return in.getFilePointer(); - } - - @Override - public void seek(long pos) throws IOException { - in.seek(pos); - seekTracker.increment(directory, name); - } - - @Override - public long length() { - return in.length(); - } - - @Override - public IndexInput slice(String sliceDescription, long offset, long length) throws IOException { - return wrapIndexInput(directory, name, in.slice(sliceDescription + "[seek_tracked]", offset, length)); - } - - @Override - public RandomAccessInput randomAccessSlice(long offset, long length) throws IOException { - final IndexInput innerSlice = in.slice("randomaccess", offset, length); - if (innerSlice instanceof RandomAccessInput) { - // slice() already supports random access - return new RandomAccessSeekCountingIndexInput(innerSlice, directory, name); - } else { - IndexInput slice = wrapIndexInput(directory, name, innerSlice); - // return default impl - return new RandomAccessInput() { - @Override - public long length() { - return slice.length(); - } - - @Override - public byte readByte(long pos) throws IOException { - slice.seek(pos); - return slice.readByte(); - } - - @Override - public short readShort(long pos) throws IOException { - slice.seek(pos); - return slice.readShort(); - } - - @Override - public int readInt(long pos) throws IOException { - slice.seek(pos); - return slice.readInt(); - } - - @Override - public long readLong(long pos) throws IOException { - slice.seek(pos); - return slice.readLong(); - } - - @Override - public String toString() { - return "RandomAccessInput(" + slice + ")"; - } - }; - } - } - - @Override - public byte readByte() throws IOException { - return in.readByte(); - } - - @Override - public void readBytes(byte[] b, int offset, int len) throws IOException { - in.readBytes(b, offset, len); - } - - @Override - public void readBytes(byte[] b, int offset, int len, boolean useBuffer) throws IOException { - in.readBytes(b, offset, len, useBuffer); - } - - @Override - public short readShort() throws IOException { - return in.readShort(); - } - - @Override - public int readInt() throws IOException { - return in.readInt(); - } - - @Override - public int readVInt() throws IOException { - return in.readVInt(); - } - - @Override - public int readZInt() throws IOException { - return in.readZInt(); - } - - @Override - public long readLong() throws IOException { - return in.readLong(); - } - - @Override - public long readVLong() throws IOException { - return in.readVLong(); - } - - @Override - public long readZLong() throws IOException { - return in.readZLong(); - } - - @Override - public String readString() throws IOException { - return in.readString(); - } - - @Override - public Map readMapOfStrings() throws IOException { - return in.readMapOfStrings(); - } - - @Override - public Set readSetOfStrings() throws IOException { - return in.readSetOfStrings(); - } - - @Override - public void skipBytes(long numBytes) throws IOException { - in.skipBytes(numBytes); - } - - @Override - public void readFloats(float[] floats, int offset, int len) throws IOException { - in.readFloats(floats, offset, len); - } - - @Override - public void readLongs(long[] dst, int offset, int length) throws IOException { - in.readLongs(dst, offset, length); - } - - @Override - public void readInts(int[] dst, int offset, int length) throws IOException { - in.readInts(dst, offset, length); - } - - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/ShardSeekStats.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/ShardSeekStats.java deleted file mode 100644 index 1f904c0807fb..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/ShardSeekStats.java +++ /dev/null @@ -1,36 +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.test.seektracker; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Writeable; -import org.elasticsearch.xcontent.ToXContentObject; -import org.elasticsearch.xcontent.XContentBuilder; - -import java.io.IOException; -import java.util.Map; - -public record ShardSeekStats(String shard, Map seeksPerFile) implements Writeable, ToXContentObject { - - public ShardSeekStats(StreamInput in) throws IOException { - this(in.readString(), in.readMap(StreamInput::readLong)); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(this.shard); - out.writeMap(this.seeksPerFile, StreamOutput::writeLong); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("shard", this.shard).field("seeks", seeksPerFile).endObject(); - } -} diff --git a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/TransportSeekStatsAction.java b/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/TransportSeekStatsAction.java deleted file mode 100644 index bd1c35302b04..000000000000 --- a/test/external-modules/seek-tracking-directory/src/main/java/org/elasticsearch/test/seektracker/TransportSeekStatsAction.java +++ /dev/null @@ -1,83 +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.test.seektracker; - -import org.elasticsearch.action.FailedNodeException; -import org.elasticsearch.action.support.ActionFilters; -import org.elasticsearch.action.support.nodes.TransportNodesAction; -import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.cluster.service.ClusterService; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.tasks.Task; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportService; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class TransportSeekStatsAction extends TransportNodesAction { - - private final SeekStatsService seekStatsService; - - @Inject - public TransportSeekStatsAction( - ThreadPool threadPool, - ClusterService clusterService, - TransportService transportService, - ActionFilters actionFilters, - SeekStatsService seekStatsService - ) { - super( - SeekTrackerPlugin.SEEK_STATS_ACTION.name(), - clusterService, - transportService, - actionFilters, - SeekStatsRequest::new, - threadPool.executor(ThreadPool.Names.MANAGEMENT) - ); - this.seekStatsService = seekStatsService; - } - - @Override - protected SeekStatsResponse newResponse(SeekStatsRequest request, List seekStats, List failures) { - return new SeekStatsResponse(clusterService.getClusterName(), seekStats, failures); - } - - @Override - protected SeekStatsRequest newNodeRequest(SeekStatsRequest request) { - // TODO don't wrap the whole top-level request, it contains heavy and irrelevant DiscoveryNode things; see #100878 - return request; - } - - @Override - protected NodeSeekStats newNodeResponse(StreamInput in, DiscoveryNode node) throws IOException { - return new NodeSeekStats(in); - } - - @Override - protected NodeSeekStats nodeOperation(SeekStatsRequest request, Task task) { - Map> seeks = new HashMap<>(); - if (request.getIndices().length == 0) { - for (Map.Entry entry : seekStatsService.getSeekStats().entrySet()) { - seeks.put(entry.getKey(), entry.getValue().getSeeks()); - } - } else { - for (String index : request.getIndices()) { - IndexSeekTracker indexSeekTracker = seekStatsService.getSeekStats(index); - if (indexSeekTracker != null) { - seeks.put(index, indexSeekTracker.getSeeks()); - } - } - } - return new NodeSeekStats(clusterService.localNode(), seeks); - } -} From 9abfcf2ada522910b10b4d5e2056d6dc635a1cb8 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Wed, 12 Jun 2024 07:50:02 +0200 Subject: [PATCH 26/34] Optimize CompositeBytesReference.toBytesRef (#109288) No need to copy to an intermediary (and oversized) `BytesRefBuilder` here. We can do with a single round of copying and a single `byte[]` allocation since we know all the sizes. This method is called here and there e.g. when indexing large documents so fixing this softens the blow from copying to fresh on-heap bytes by more than 2x at least. --- .../common/bytes/CompositeBytesReference.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/common/bytes/CompositeBytesReference.java b/server/src/main/java/org/elasticsearch/common/bytes/CompositeBytesReference.java index b63d722df9b4..65a3bf95336c 100644 --- a/server/src/main/java/org/elasticsearch/common/bytes/CompositeBytesReference.java +++ b/server/src/main/java/org/elasticsearch/common/bytes/CompositeBytesReference.java @@ -9,7 +9,6 @@ package org.elasticsearch.common.bytes; import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.BytesRefIterator; import org.apache.lucene.util.RamUsageEstimator; @@ -172,18 +171,33 @@ public final class CompositeBytesReference extends AbstractBytesReference { @Override public BytesRef toBytesRef() { - BytesRefBuilder builder = new BytesRefBuilder(); - builder.grow(length()); + final byte[] result = new byte[length]; + int offset = 0; + for (BytesReference reference : references) { + if (reference.hasArray()) { + int len = reference.length(); + System.arraycopy(reference.array(), reference.arrayOffset(), result, offset, len); + offset += len; + } else { + offset = copyViaIterator(reference, result, offset); + } + } + assert offset == result.length; + return new BytesRef(result); + } + + private static int copyViaIterator(BytesReference reference, byte[] result, int offset) { BytesRef spare; - BytesRefIterator iterator = iterator(); + BytesRefIterator iterator = reference.iterator(); try { while ((spare = iterator.next()) != null) { - builder.append(spare); + System.arraycopy(spare.bytes, spare.offset, result, offset, spare.length); + offset += spare.length; } } catch (IOException ex) { throw new AssertionError("won't happen", ex); // this is really an error since we don't do IO in our bytesreferences } - return builder.toBytesRef(); + return offset; } @Override From a7cd581201efcadf2a8006b09ee19461303b67a1 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Wed, 12 Jun 2024 08:58:37 +0200 Subject: [PATCH 27/34] Update sparse file tracker `complete` pointer on progress (#109247) This change updates the complete pointer when a Gap makes progress. --- .../ProgressListenableActionFuture.java | 51 +++++++++++---- .../blobcache/common/SparseFileTracker.java | 38 ++++++++++-- .../ProgressListenableActionFutureTests.java | 42 ++++++++++++- .../common/SparseFileTrackerTests.java | 62 +++++++++++++++++++ 4 files changed, 175 insertions(+), 18 deletions(-) diff --git a/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/ProgressListenableActionFuture.java b/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/ProgressListenableActionFuture.java index 6381f1c1e211..00cc9554a64e 100644 --- a/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/ProgressListenableActionFuture.java +++ b/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/ProgressListenableActionFuture.java @@ -7,12 +7,16 @@ package org.elasticsearch.blobcache.common; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.core.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.function.LongConsumer; import java.util.function.Supplier; /** @@ -24,29 +28,40 @@ import java.util.function.Supplier; */ class ProgressListenableActionFuture extends PlainActionFuture { + private static final Logger logger = LogManager.getLogger(ProgressListenableActionFuture.class); + private record PositionAndListener(long position, ActionListener listener) {} - protected final long start; - protected final long end; + final long start; + final long end; - // modified under 'this' mutex - private volatile List listeners; - protected volatile long progress; + /** + * A consumer that accepts progress made by this {@link ProgressListenableActionFuture}. The consumer is called before listeners are + * notified of the updated progress value in {@link #onProgress(long)} if the value is less than the actual end. The consumer can be + * called with out-of-order progress values. + */ + @Nullable + private final LongConsumer progressConsumer; + + private List listeners; + private long progress; private volatile boolean completed; /** * Creates a {@link ProgressListenableActionFuture} that accepts the progression * to be within {@code start} (inclusive) and {@code end} (exclusive) values. * - * @param start the start (inclusive) - * @param end the end (exclusive) + * @param start the start (inclusive) + * @param end the end (exclusive) + * @param progressConsumer a consumer that accepts the progress made by this {@link ProgressListenableActionFuture} */ - ProgressListenableActionFuture(long start, long end) { + ProgressListenableActionFuture(long start, long end, @Nullable LongConsumer progressConsumer) { super(); this.start = start; this.end = end; this.progress = start; this.completed = false; + this.progressConsumer = progressConsumer; assert invariant(); } @@ -108,6 +123,9 @@ class ProgressListenableActionFuture extends PlainActionFuture { } } if (listenersToExecute != null) { + if (progressConsumer != null) { + safeAcceptProgress(progressConsumer, progressValue); + } listenersToExecute.forEach(listener -> executeListener(listener, () -> progressValue)); } assert invariant(); @@ -115,8 +133,8 @@ class ProgressListenableActionFuture extends PlainActionFuture { @Override public void onResponse(Long result) { - if (result == null || result < start || end < result) { - assert false : start + " < " + result + " < " + end; + if (result == null || end != result) { + assert false : result + " != " + end; throw new IllegalArgumentException("Invalid completion value [start=" + start + ",end=" + end + ",response=" + result + ']'); } ensureNotCompleted(); @@ -143,6 +161,7 @@ class ProgressListenableActionFuture extends PlainActionFuture { synchronized (this) { assert completed == false; completed = true; + assert listeners == null || listeners.stream().allMatch(l -> progress < l.position() && l.position() <= end); listenersToExecute = this.listeners; listeners = null; } @@ -189,8 +208,18 @@ class ProgressListenableActionFuture extends PlainActionFuture { } } + private static void safeAcceptProgress(LongConsumer consumer, long progress) { + assert consumer != null; + try { + consumer.accept(progress); + } catch (Exception e) { + assert false : e; + logger.warn("Failed to consume progress value", e); + } + } + @Override - public String toString() { + public synchronized String toString() { return "ProgressListenableActionFuture[start=" + start + ", end=" diff --git a/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/SparseFileTracker.java b/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/SparseFileTracker.java index 6e6a11fbddc9..e3ff6a7ae4c7 100644 --- a/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/SparseFileTracker.java +++ b/x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/SparseFileTracker.java @@ -18,6 +18,7 @@ import java.util.Comparator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; +import java.util.function.LongConsumer; /** * Keeps track of the contents of a file that may not be completely present. @@ -199,7 +200,7 @@ public class SparseFileTracker { final Range newPendingRange = new Range( targetRange.start, range.end(), - new ProgressListenableActionFuture(targetRange.start, range.end()) + new ProgressListenableActionFuture(targetRange.start, range.end(), progressConsumer(targetRange.start)) ); ranges.add(newPendingRange); pendingRanges.add(newPendingRange); @@ -218,7 +219,7 @@ public class SparseFileTracker { final Range newPendingRange = new Range( targetRange.start, newPendingRangeEnd, - new ProgressListenableActionFuture(targetRange.start, newPendingRangeEnd) + new ProgressListenableActionFuture(targetRange.start, newPendingRangeEnd, progressConsumer(targetRange.start)) ); ranges.add(newPendingRange); pendingRanges.add(newPendingRange); @@ -260,6 +261,15 @@ public class SparseFileTracker { } } + private LongConsumer progressConsumer(long rangeStart) { + assert Thread.holdsLock(ranges); + if (rangeStart == complete) { + return this::updateCompletePointer; + } else { + return null; + } + } + public boolean checkAvailable(long upTo) { assert upTo <= length : "tried to check availability up to [" + upTo + "] but length is only [" + length + "]"; return complete >= upTo; @@ -464,11 +474,27 @@ public class SparseFileTracker { private void maybeUpdateCompletePointer(Range gapRange) { assert Thread.holdsLock(ranges); if (gapRange.start == 0) { - assert complete <= gapRange.end; - complete = gapRange.end; + updateCompletePointerHoldingLock(gapRange.end); } } + private void updateCompletePointerHoldingLock(long value) { + assert Thread.holdsLock(ranges); + assert complete <= value : complete + ">" + value; + complete = value; + } + + private void updateCompletePointer(long value) { + synchronized (ranges) { + updateCompletePointerHoldingLock(value); + } + } + + // used in tests + long getComplete() { + return complete; + } + private boolean assertGapRangePending(Range gapRange) { synchronized (ranges) { assert invariant(); @@ -535,9 +561,9 @@ public class SparseFileTracker { /** * Range in the file corresponding to the current gap */ - public final Range range; + private final Range range; - Gap(Range range) { + private Gap(Range range) { assert range.start < range.end : range.start + "-" + range.end; this.range = range; } diff --git a/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/ProgressListenableActionFutureTests.java b/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/ProgressListenableActionFutureTests.java index a94a3214fdd9..4490d087cec1 100644 --- a/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/ProgressListenableActionFutureTests.java +++ b/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/ProgressListenableActionFutureTests.java @@ -233,9 +233,49 @@ public class ProgressListenableActionFutureTests extends ESTestCase { assertThat(future.isDone(), is(true)); } + public void testLongConsumerCalledOnProgressUpdate() { + // min length of 2 to have at least one progress update before reaching the end + long length = randomLongBetween(2L, ByteSizeUnit.TB.toBytes(1L)); + long start = randomLongBetween(Long.MIN_VALUE, Long.MAX_VALUE - length); + long end = start + length; + + var consumed = new HashSet(); + var future = new ProgressListenableActionFuture( + start, + end, + p -> assertThat("LongConsumer should not consumed the same value twice", consumed.add(p), equalTo(true)) + ); + + long position = start; + int iters = randomIntBetween(10, 25); + for (int i = 0; i < iters && position < end - 1L; i++) { + var progress = randomLongBetween(position + 1L, end - 1L); + + var listener = new PlainActionFuture(); + future.addListener( + ActionListener.runBefore( + listener, + () -> assertThat( + "LongConsumer should have been called before listener completion", + consumed.contains(progress), + equalTo(true) + ) + ), + randomLongBetween(position + 1L, progress) + ); + future.onProgress(progress); + + assertThat(consumed.contains(progress), equalTo(true)); + assertThat(listener.isDone(), equalTo(true)); + position = progress; + } + future.onProgress(end); + assertThat("LongConsumer is not called when progress is updated to the end", consumed.contains(end), equalTo(false)); + } + private static ProgressListenableActionFuture randomFuture() { final long delta = randomLongBetween(1L, ByteSizeUnit.TB.toBytes(1L)); final long start = randomLongBetween(Long.MIN_VALUE, Long.MAX_VALUE - delta); - return new ProgressListenableActionFuture(start, start + delta); + return new ProgressListenableActionFuture(start, start + delta, null); } } diff --git a/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/SparseFileTrackerTests.java b/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/SparseFileTrackerTests.java index 5973b90c814d..fda560ccb2e2 100644 --- a/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/SparseFileTrackerTests.java +++ b/x-pack/plugin/blob-cache/src/test/java/org/elasticsearch/blobcache/common/SparseFileTrackerTests.java @@ -517,6 +517,68 @@ public class SparseFileTrackerTests extends ESTestCase { assertThat(completedRanges, equalTo(expectedCompletedRanges)); } + public void testCompletePointerUpdatesOnProgress() { + // min length of 2 to have at least one progress update before reaching the end + byte[] bytes = new byte[between(2, 1024)]; + var tracker = new SparseFileTracker(getTestName(), bytes.length); + + long position = 0L; + for (int i = 0; i < 25 && position < tracker.getLength() - 1L; i++) { + var progress = randomLongBetween(position + 1L, tracker.getLength() - 1L); + + var listener = new PlainActionFuture(); + var gaps = tracker.waitForRange( + ByteRange.of(position, progress), + ByteRange.of(position, progress), + ActionListener.runBefore(listener, () -> assertThat(tracker.getComplete(), equalTo(progress))) + ); + assertThat(listener.isDone(), equalTo(false)); + assertThat(gaps, hasSize(1)); + + gaps.forEach(gap -> { + long latestUpdatedCompletePointer = gap.start(); + + for (long j = gap.start(); j < gap.end(); j++) { + final PlainActionFuture awaitingListener; + if (randomBoolean()) { + awaitingListener = new PlainActionFuture<>(); + var moreGaps = tracker.waitForRange( + ByteRange.of(gap.start(), j + 1L), + ByteRange.of(gap.start(), j + 1L), + awaitingListener + ); + assertThat(moreGaps.isEmpty(), equalTo(true)); + } else { + awaitingListener = null; + } + + assertThat(bytes[toIntBytes(j)], equalTo(UNAVAILABLE)); + bytes[toIntBytes(j)] = AVAILABLE; + gap.onProgress(j + 1L); + + if (awaitingListener != null && j < gap.end() - 1L) { + assertThat( + "Complete pointer should have been updated when a listener is waiting for the gap to be completed", + tracker.getComplete(), + equalTo(j + 1L) + ); + assertThat(awaitingListener.isDone(), equalTo(true)); + latestUpdatedCompletePointer = tracker.getComplete(); + } else { + assertThat( + "Complete pointer is not updated if no listeners are waiting for the gap to be completed", + tracker.getComplete(), + equalTo(latestUpdatedCompletePointer) + ); + } + } + gap.onCompletion(); + assertThat(tracker.getComplete(), equalTo(gap.end())); + }); + position = progress; + } + } + private static void checkRandomAbsentRange(byte[] fileContents, SparseFileTracker sparseFileTracker, boolean expectExact) { final long checkStart = randomLongBetween(0, fileContents.length - 1); final long checkEnd = randomLongBetween(checkStart, fileContents.length); From faa9648a2923d4cbfd744938951962d93b2edf6c Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Wed, 12 Jun 2024 10:53:47 +0200 Subject: [PATCH 28/34] Disable auto-expand functionality for stateless indices (#108797) Replicas are automatically managed in stateless, hence auto-expand replicas needs to be disabled for stateless indices in order for it not to conflict with the automatic management of replicas for indices. As a result, stateless indices won't see auto-expand take any effect due to applying auto-expand replicas from the ES codebase. There is an edge-case for indices that do set number of replicas to 0 manually as well as auto_expand_replicas as part of index settings: in that case we force such value to be 1 rather than 0. --- .../cluster/metadata/AutoExpandReplicas.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/AutoExpandReplicas.java b/server/src/main/java/org/elasticsearch/cluster/metadata/AutoExpandReplicas.java index 106f4c1e4e38..9fb44e0106df 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/AutoExpandReplicas.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/AutoExpandReplicas.java @@ -100,13 +100,6 @@ public record AutoExpandReplicas(int minReplicas, int maxReplicas, boolean enabl public int getDesiredNumberOfReplicas(IndexMetadata indexMetadata, RoutingAllocation allocation) { assert enabled : "should only be called when enabled"; - // Make sure in stateless auto-expand indices always have 1 replica to ensure all shard roles are always present - if (Objects.equals( - indexMetadata.getSettings().get(ExistingShardsAllocator.EXISTING_SHARDS_ALLOCATOR_SETTING.getKey()), - "stateless" - )) { - return 1; - } int numMatchingDataNodes = 0; for (DiscoveryNode discoveryNode : allocation.nodes().getDataNodes().values()) { Decision decision = allocation.deciders().shouldAutoExpandToNode(indexMetadata, discoveryNode, allocation); @@ -150,9 +143,22 @@ public record AutoExpandReplicas(int minReplicas, int maxReplicas, boolean enabl for (final IndexMetadata indexMetadata : metadata) { if (indexMetadata.getState() == IndexMetadata.State.OPEN || isIndexVerifiedBeforeClosed(indexMetadata)) { AutoExpandReplicas autoExpandReplicas = indexMetadata.getAutoExpandReplicas(); + // Make sure auto-expand is applied only when configured, and entirely disabled in stateless if (autoExpandReplicas.enabled() == false) { continue; } + // Special case for stateless indices: auto-expand is disabled, unless number_of_replicas has been set + // manually to 0 via index settings, which needs to be converted to 1. + if (Objects.equals( + indexMetadata.getSettings().get(ExistingShardsAllocator.EXISTING_SHARDS_ALLOCATOR_SETTING.getKey()), + "stateless" + )) { + if (indexMetadata.getNumberOfReplicas() == 0) { + nrReplicasChanged.computeIfAbsent(1, ArrayList::new).add(indexMetadata.getIndex().getName()); + } else { + continue; + } + } if (allocation == null) { allocation = allocationSupplier.get(); } From ac6013aa4b196f1cf183bf50fe3ef60590833886 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 12 Jun 2024 19:07:16 +1000 Subject: [PATCH 29/34] Extend assertion expiry in SAML auth tests (#109607) Sometimes buildkite seems to swallow time. This commit extends some of the authentication/session expiry times to compensate. Relates: #109299 --- .../authc/saml/SamlAuthenticatorTests.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java index 16c7b39fa695..83f09bad0d27 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java @@ -592,17 +592,23 @@ public class SamlAuthenticatorTests extends SamlResponseHandlerTests { } public void testExpiredAuthnStatementSessionIsRejected() throws Exception { - Instant now = clock.instant(); - String xml = getSimpleResponseAsString(now); + final Instant now = clock.instant(); + final int sessionExpirySeconds = 60; + final Instant subjectConfirmationValidUntil = now.plusSeconds(500); + final Instant sessionValidUntil = now.plusSeconds(sessionExpirySeconds); + final String xml = SamlUtils.getXmlContent( + getSimpleResponse(now, randomId(), randomId(), subjectConfirmationValidUntil, sessionValidUntil), + false + ); SamlToken token = token(signResponse(xml)); assertThat(authenticator.authenticate(token), notNullValue()); // and still valid if we advance partway through the session expiry time - clock.fastForwardSeconds(30); + clock.fastForwardSeconds(sessionExpirySeconds / 2); assertThat(authenticator.authenticate(token), notNullValue()); // and still valid if we advance past the expiry time, but allow for clock skew - clock.fastForwardSeconds((int) (30 + maxSkew.seconds() / 2)); + clock.fastForwardSeconds((int) (sessionExpirySeconds / 2 + maxSkew.seconds() / 2)); assertThat(authenticator.authenticate(token), notNullValue()); // but fails once we get past the clock skew allowance @@ -1442,8 +1448,8 @@ public class SamlAuthenticatorTests extends SamlResponseHandlerTests { } private Response getSimpleResponse(Instant now, String nameId, String sessionindex) { - Instant subjectConfirmationValidUntil = now.plusSeconds(120); - Instant sessionValidUntil = now.plusSeconds(60); + Instant subjectConfirmationValidUntil = now.plusSeconds(500); + Instant sessionValidUntil = now.plusSeconds(300); return getSimpleResponse(now, nameId, sessionindex, subjectConfirmationValidUntil, sessionValidUntil); } @@ -1565,7 +1571,7 @@ public class SamlAuthenticatorTests extends SamlResponseHandlerTests { String nameId, String sessionindex ) { - Instant validUntil = now.plusSeconds(30); + Instant validUntil = now.plusSeconds(300); String xml = " Date: Wed, 12 Jun 2024 12:15:53 +0200 Subject: [PATCH 30/34] Speedup ContextIndexSearcher (#109601) We can do a little better here and create less garbage + save cycles for method calls when doing all the sorting. --- .../search/internal/ContextIndexSearcher.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java b/server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java index 0263c6e83b17..cba2cf761e6f 100644 --- a/server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java +++ b/server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java @@ -49,7 +49,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.PriorityQueue; @@ -255,13 +254,11 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable { // Make a copy so we can sort: List sortedLeaves = new ArrayList<>(leaves); // Sort by maxDoc, descending: - final Comparator leafComparator = Comparator.comparingInt(l -> l.reader().maxDoc()); - sortedLeaves.sort(leafComparator.reversed()); + sortedLeaves.sort((c1, c2) -> Integer.compare(c2.reader().maxDoc(), c1.reader().maxDoc())); // we add the groups on a priority queue, so we can add orphan leafs to the smallest group - final Comparator> groupComparator = Comparator.comparingInt( - l -> l.stream().mapToInt(lr -> lr.reader().maxDoc()).sum() + final PriorityQueue> queue = new PriorityQueue<>( + (c1, c2) -> Integer.compare(sumMaxDocValues(c1), sumMaxDocValues(c2)) ); - final PriorityQueue> queue = new PriorityQueue<>(groupComparator); long docSum = 0; List group = new ArrayList<>(); for (LeafReaderContext ctx : sortedLeaves) { @@ -297,6 +294,14 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable { return slices; } + private static int sumMaxDocValues(List l) { + int sum = 0; + for (LeafReaderContext lr : l) { + sum += lr.reader().maxDoc(); + } + return sum; + } + @Override public T search(Query query, CollectorManager collectorManager) throws IOException { final C firstCollector = collectorManager.newCollector(); @@ -337,7 +342,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable { throw new IllegalStateException("CollectorManager does not always produce collectors with the same score mode"); } } - final List> listTasks = new ArrayList<>(); + final List> listTasks = new ArrayList<>(leafSlices.length); for (int i = 0; i < leafSlices.length; ++i) { final LeafReaderContext[] leaves = leafSlices[i].leaves; final C collector = collectors.get(i); From 3b28c2f6a4dbadb007080f9355db7782bb603e2a Mon Sep 17 00:00:00 2001 From: Nick Tindall Date: Wed, 12 Jun 2024 20:47:08 +1000 Subject: [PATCH 31/34] Consider error_trace supported by all endpoints (#109613) Closes #109612 --- docs/changelog/109613.yaml | 6 ++++++ .../java/org/elasticsearch/common/util/set/Sets.java | 9 +++++++++ .../java/org/elasticsearch/rest/BaseRestHandler.java | 3 ++- .../main/java/org/elasticsearch/rest/RestResponse.java | 1 + .../org/elasticsearch/rest/BaseRestHandlerTests.java | 1 + 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/109613.yaml diff --git a/docs/changelog/109613.yaml b/docs/changelog/109613.yaml new file mode 100644 index 000000000000..21d152ac1d6d --- /dev/null +++ b/docs/changelog/109613.yaml @@ -0,0 +1,6 @@ +pr: 109613 +summary: Consider `error_trace` supported by all endpoints +area: Infra/REST API +type: bug +issues: + - 109612 diff --git a/server/src/main/java/org/elasticsearch/common/util/set/Sets.java b/server/src/main/java/org/elasticsearch/common/util/set/Sets.java index 75e5717d41b9..5434dc91238c 100644 --- a/server/src/main/java/org/elasticsearch/common/util/set/Sets.java +++ b/server/src/main/java/org/elasticsearch/common/util/set/Sets.java @@ -135,6 +135,15 @@ public final class Sets { return union; } + @SafeVarargs + public static Set union(Set first, Set... others) { + Set union = new HashSet<>(first); + for (Set other : others) { + union.addAll(other); + } + return union; + } + /** * The intersection of two sets. Namely, the resulting set contains all the elements that are in both sets. * Neither input is mutated by this operation, an entirely new set is returned. diff --git a/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java b/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java index f91b08439422..a17bc885f6b6 100644 --- a/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java +++ b/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java @@ -83,7 +83,7 @@ public abstract class BaseRestHandler implements RestHandler { // check if the query has any parameters that are not in the supported set (if declared) Set supported = allSupportedParameters(); if (supported != null) { - var allSupported = Sets.union(ALWAYS_SUPPORTED, supported); + var allSupported = Sets.union(RestResponse.RESPONSE_PARAMS, ALWAYS_SUPPORTED, supported); if (allSupported.containsAll(request.params().keySet()) == false) { Set unsupported = Sets.difference(request.params().keySet(), allSupported); throw new IllegalArgumentException(unrecognized(request, unsupported, allSupported, "parameter")); @@ -97,6 +97,7 @@ public abstract class BaseRestHandler implements RestHandler { // use a sorted set so the unconsumed parameters appear in a reliable sorted order final SortedSet unconsumedParams = request.unconsumedParams() .stream() + .filter(p -> RestResponse.RESPONSE_PARAMS.contains(p) == false) .filter(p -> responseParams(request.getRestApiVersion()).contains(p) == false) .collect(Collectors.toCollection(TreeSet::new)); diff --git a/server/src/main/java/org/elasticsearch/rest/RestResponse.java b/server/src/main/java/org/elasticsearch/rest/RestResponse.java index 8cc0e35a6480..5502ab1ba094 100644 --- a/server/src/main/java/org/elasticsearch/rest/RestResponse.java +++ b/server/src/main/java/org/elasticsearch/rest/RestResponse.java @@ -37,6 +37,7 @@ import static org.elasticsearch.rest.RestController.ELASTIC_PRODUCT_HTTP_HEADER; public final class RestResponse implements Releasable { public static final String TEXT_CONTENT_TYPE = "text/plain; charset=UTF-8"; + public static final Set RESPONSE_PARAMS = Set.of("error_trace"); static final String STATUS = "status"; diff --git a/server/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java b/server/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java index b5c6b28693b3..2318614c241e 100644 --- a/server/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java +++ b/server/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java @@ -235,6 +235,7 @@ public class BaseRestHandlerTests extends ESTestCase { params.put("filter_path", randomAlphaOfLength(8)); params.put("pretty", randomFrom("true", "false", "", null)); params.put("human", null); + params.put("error_trace", randomFrom("true", "false", null)); RestRequest request = new FakeRestRequest.Builder(xContentRegistry()).withParams(params).build(); RestChannel channel = new FakeRestChannel(request, randomBoolean(), 1); handler.handleRequest(request, channel, mockClient); From 67f85ebea099fcc027997624c7577afef4311cd9 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Wed, 12 Jun 2024 13:38:32 +0200 Subject: [PATCH 32/34] DenseVectorMappingUpdateIT BWC fix (#109620) --- muted-tests.yml | 2 -- .../upgrades/DenseVectorMappingUpdateIT.java | 14 +++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index 03a0df5cc395..dea7741715a7 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -59,8 +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: DenseVectorMappingUpdateIT - issue: "https://github.com/elastic/elasticsearch/issues/109571" # Examples: # diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java index 99cbef655693..0830c1b766a2 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java @@ -91,9 +91,13 @@ public class DenseVectorMappingUpdateIT extends AbstractRollingUpgradeTestCase { .startObject("properties") .startObject("embedding") .field("type", "dense_vector") + .field("index", "true") .field("dims", 4) + .field("similarity", "cosine") .startObject("index_options") .field("type", "hnsw") + .field("m", "16") + .field("ef_construction", "100") .endObject() .endObject() .endObject() @@ -109,7 +113,7 @@ public class DenseVectorMappingUpdateIT extends AbstractRollingUpgradeTestCase { int expectedCount = 10; - assertCount("test_index", expectedCount); + assertCount(indexName, expectedCount); if (isUpgradedCluster() && clusterSupportsDenseVectorTypeUpdate()) { Request updateMapping = new Request("PUT", "/" + indexName + "/_mapping"); @@ -118,9 +122,13 @@ public class DenseVectorMappingUpdateIT extends AbstractRollingUpgradeTestCase { .startObject("properties") .startObject("embedding") .field("type", "dense_vector") + .field("index", "true") .field("dims", 4) + .field("similarity", "cosine") .startObject("index_options") .field("type", "int8_hnsw") + .field("m", "16") + .field("ef_construction", "100") .endObject() .endObject() .endObject() @@ -132,7 +140,7 @@ public class DenseVectorMappingUpdateIT extends AbstractRollingUpgradeTestCase { index.setJsonEntity(BULK2); assertOK(client().performRequest(index)); expectedCount = 20; - assertCount("test_index", expectedCount); + assertCount(indexName, expectedCount); } } } @@ -152,7 +160,7 @@ public class DenseVectorMappingUpdateIT extends AbstractRollingUpgradeTestCase { Map response = entityAsMap(client().performRequest(new Request("GET", "_nodes"))); Map nodes = (Map) response.get("nodes"); - Predicate> nodeSupportsBulkApi = n -> Version.fromString(n.get("version").toString()).onOrAfter(Version.V_8_14_0); + Predicate> nodeSupportsBulkApi = n -> Version.fromString(n.get("version").toString()).onOrAfter(Version.V_8_15_0); return nodes.values().stream().map(o -> (Map) o).allMatch(nodeSupportsBulkApi); } From d846223593b7986d4148a5fde9086cfba79bd232 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Wed, 12 Jun 2024 07:51:42 -0400 Subject: [PATCH 33/34] Mute all collapse tests for 8.13 (#109594) related to: https://github.com/elastic/elasticsearch/issues/109476 --- .../test/search.retrievers/10_standard_retriever.yml | 5 +++++ .../rest-api-spec/test/search/110_field_collapsing.yml | 6 +++++- .../test/search/111_field_collapsing_with_max_score.yml | 5 +++++ .../test/search/112_field_collapsing_with_rescore.yml | 5 +++++ .../test/search/115_multiple_field_collapsing.yml | 6 ++++++ .../resources/rest-api-spec/test/60_collapse.yml | 6 +++++- 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.retrievers/10_standard_retriever.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.retrievers/10_standard_retriever.yml index fcd5b49c984c..99d723664097 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.retrievers/10_standard_retriever.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.retrievers/10_standard_retriever.yml @@ -473,6 +473,11 @@ setup: --- "standard retriever collapse": + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" - do: search: index: animals diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/110_field_collapsing.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/110_field_collapsing.yml index c10d3c48259f..2eb8b729d2c6 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/110_field_collapsing.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/110_field_collapsing.yml @@ -1,4 +1,9 @@ setup: + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" - do: indices.create: index: test @@ -85,7 +90,6 @@ setup: --- "field collapsing and from": - - do: search: rest_total_hits_as_int: true diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/111_field_collapsing_with_max_score.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/111_field_collapsing_with_max_score.yml index 3c0364bb7834..b05916aa96e4 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/111_field_collapsing_with_max_score.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/111_field_collapsing_with_max_score.yml @@ -1,4 +1,9 @@ setup: + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" - requires: cluster_features: ["gte_v8.10.0"] reason: Collapse with max score was fixed in 8.10.0 diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/112_field_collapsing_with_rescore.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/112_field_collapsing_with_rescore.yml index 67819881f1b5..08a2c9c89e33 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/112_field_collapsing_with_rescore.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/112_field_collapsing_with_rescore.yml @@ -1,4 +1,9 @@ setup: + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" - requires: cluster_features: "gte_v8.15.0" reason: Collapse with rescore added in 8.15.0 diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/115_multiple_field_collapsing.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/115_multiple_field_collapsing.yml index 5bc3f8cde65e..69fd8f61261c 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/115_multiple_field_collapsing.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/115_multiple_field_collapsing.yml @@ -1,3 +1,9 @@ +setup: + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" --- "two levels fields collapsing": diff --git a/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml index 0c87424a88fe..84f162cdae94 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml +++ b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml @@ -1,5 +1,9 @@ setup: - + - skip: + reason: "https://github.com/elastic/elasticsearch/issues/109476" + known_issues: + - cluster_feature: "gte_v8.13.0" + fixed_by: "gte_v8.14.0" - requires: cluster_features: ["gte_v8.0.0"] reason: "collapse on unsigned_long was added in 8.0" From daf30f96dc700ceb944c055c9bf1b17ee54e3abf Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Wed, 12 Jun 2024 14:01:44 +0200 Subject: [PATCH 34/34] Introduce and use a few more empty response type constants to o.e.c.lucene.Lucene (#109619) Shortening a few more pieces of production code using constants, potentially saving a little in code size and allocation in some cases. --- .../elasticsearch/action/search/DfsQueryPhase.java | 3 ++- .../action/search/SearchPhaseController.java | 6 +++--- .../elasticsearch/action/search/SearchResponse.java | 4 ++-- .../action/search/SearchResponseMerger.java | 3 ++- .../org/elasticsearch/common/lucene/Lucene.java | 5 ++++- .../grouping/SinglePassGroupingCollector.java | 3 ++- .../lucene/grouping/TopFieldGroups.java | 3 ++- .../java/org/elasticsearch/search/SearchHits.java | 2 +- .../aggregations/metrics/TopHitsAggregator.java | 7 +------ .../org/elasticsearch/search/query/QueryPhase.java | 13 ++----------- .../search/query/QueryPhaseCollectorManager.java | 2 +- .../xpack/search/MutableSearchResponse.java | 4 ++-- .../xpack/security/profile/ProfileService.java | 8 ++------ 13 files changed, 26 insertions(+), 37 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/search/DfsQueryPhase.java b/server/src/main/java/org/elasticsearch/action/search/DfsQueryPhase.java index c5c35b1980a5..9ddac7f13eb5 100644 --- a/server/src/main/java/org/elasticsearch/action/search/DfsQueryPhase.java +++ b/server/src/main/java/org/elasticsearch/action/search/DfsQueryPhase.java @@ -9,6 +9,7 @@ package org.elasticsearch.action.search; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.join.ScoreMode; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.index.query.NestedQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.SearchPhaseResult; @@ -152,7 +153,7 @@ final class DfsQueryPhase extends SearchPhase { scoreDocs.sort(Comparator.comparingInt(scoreDoc -> scoreDoc.doc)); String nestedPath = dfsKnnResults.getNestedPath(); QueryBuilder query = new KnnScoreDocQueryBuilder( - scoreDocs.toArray(new ScoreDoc[0]), + scoreDocs.toArray(Lucene.EMPTY_SCORE_DOCS), source.knnSearch().get(i).getField(), source.knnSearch().get(i).getQueryVector() ).boost(source.knnSearch().get(i).boost()).queryName(source.knnSearch().get(i).queryName()); diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java index 1d3859b9038f..55c754545cbb 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java @@ -24,6 +24,7 @@ import org.apache.lucene.search.TotalHits.Relation; import org.apache.lucene.util.SetOnce; import org.elasticsearch.common.breaker.CircuitBreaker; import org.elasticsearch.common.io.stream.DelayableWriteable; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.search.TopDocsAndMaxScore; import org.elasticsearch.common.util.Maps; import org.elasticsearch.common.util.concurrent.AtomicArray; @@ -66,7 +67,6 @@ import java.util.function.Supplier; import static org.elasticsearch.search.SearchService.DEFAULT_SIZE; public final class SearchPhaseController { - private static final ScoreDoc[] EMPTY_DOCS = new ScoreDoc[0]; private final BiFunction< Supplier, @@ -195,7 +195,7 @@ public final class SearchPhaseController { return SortedTopDocs.EMPTY; } final TopDocs mergedTopDocs = mergeTopDocs(topDocs, size, ignoreFrom ? 0 : from); - final ScoreDoc[] mergedScoreDocs = mergedTopDocs == null ? EMPTY_DOCS : mergedTopDocs.scoreDocs; + final ScoreDoc[] mergedScoreDocs = mergedTopDocs == null ? Lucene.EMPTY_SCORE_DOCS : mergedTopDocs.scoreDocs; ScoreDoc[] scoreDocs = mergedScoreDocs; int numSuggestDocs = 0; if (reducedCompletionSuggestions.isEmpty() == false) { @@ -907,6 +907,6 @@ public final class SearchPhaseController { Object[] collapseValues, int numberOfCompletionsSuggestions ) { - public static final SortedTopDocs EMPTY = new SortedTopDocs(EMPTY_DOCS, false, null, null, null, 0); + public static final SortedTopDocs EMPTY = new SortedTopDocs(Lucene.EMPTY_SCORE_DOCS, false, null, null, null, 0); } } diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchResponse.java b/server/src/main/java/org/elasticsearch/action/search/SearchResponse.java index e2443566786a..45cb11869108 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchResponse.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchResponse.java @@ -8,7 +8,6 @@ package org.elasticsearch.action.search; -import org.apache.lucene.search.TotalHits; import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.OriginalIndices; @@ -18,6 +17,7 @@ import org.elasticsearch.common.collect.Iterators; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.util.concurrent.ConcurrentCollections; import org.elasticsearch.common.xcontent.ChunkedToXContentHelper; import org.elasticsearch.common.xcontent.ChunkedToXContentObject; @@ -1154,7 +1154,7 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO // public for tests public static SearchResponse empty(Supplier tookInMillisSupplier, Clusters clusters) { return new SearchResponse( - SearchHits.empty(new TotalHits(0L, TotalHits.Relation.EQUAL_TO), Float.NaN), + SearchHits.empty(Lucene.TOTAL_HITS_EQUAL_TO_ZERO, Float.NaN), InternalAggregations.EMPTY, null, false, diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchResponseMerger.java b/server/src/main/java/org/elasticsearch/action/search/SearchResponseMerger.java index ae8c749475c5..d393adc4e26d 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchResponseMerger.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchResponseMerger.java @@ -18,6 +18,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.search.SearchPhaseController.TopDocsStats; import org.elasticsearch.action.search.SearchResponse.Clusters; import org.elasticsearch.action.search.TransportSearchAction.SearchTimeProvider; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.search.TopDocsAndMaxScore; import org.elasticsearch.core.Releasable; import org.elasticsearch.index.shard.ShardId; @@ -177,7 +178,7 @@ public final class SearchResponseMerger implements Releasable { final TotalHits totalHits; if (searchHits.getTotalHits() == null) { // in case we didn't track total hits, we get null from each cluster, but we need to set 0 eq to the TopDocs - totalHits = new TotalHits(0, TotalHits.Relation.EQUAL_TO); + totalHits = Lucene.TOTAL_HITS_EQUAL_TO_ZERO; assert trackTotalHits == null || trackTotalHits == false; trackTotalHits = false; } else { diff --git a/server/src/main/java/org/elasticsearch/common/lucene/Lucene.java b/server/src/main/java/org/elasticsearch/common/lucene/Lucene.java index 31a4ca97aad6..36b3076c29a3 100644 --- a/server/src/main/java/org/elasticsearch/common/lucene/Lucene.java +++ b/server/src/main/java/org/elasticsearch/common/lucene/Lucene.java @@ -101,7 +101,10 @@ public class Lucene { public static final ScoreDoc[] EMPTY_SCORE_DOCS = new ScoreDoc[0]; - public static final TopDocs EMPTY_TOP_DOCS = new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), EMPTY_SCORE_DOCS); + public static final TotalHits TOTAL_HITS_EQUAL_TO_ZERO = new TotalHits(0, TotalHits.Relation.EQUAL_TO); + public static final TotalHits TOTAL_HITS_GREATER_OR_EQUAL_TO_ZERO = new TotalHits(0, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO); + + public static final TopDocs EMPTY_TOP_DOCS = new TopDocs(TOTAL_HITS_EQUAL_TO_ZERO, EMPTY_SCORE_DOCS); private Lucene() {} diff --git a/server/src/main/java/org/elasticsearch/lucene/grouping/SinglePassGroupingCollector.java b/server/src/main/java/org/elasticsearch/lucene/grouping/SinglePassGroupingCollector.java index b11a034ce4e4..85682b9e4d50 100644 --- a/server/src/main/java/org/elasticsearch/lucene/grouping/SinglePassGroupingCollector.java +++ b/server/src/main/java/org/elasticsearch/lucene/grouping/SinglePassGroupingCollector.java @@ -36,6 +36,7 @@ import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.lucene.search.TotalHits; import org.apache.lucene.search.grouping.GroupSelector; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.util.Maps; import org.elasticsearch.core.Nullable; import org.elasticsearch.index.mapper.MappedFieldType; @@ -202,7 +203,7 @@ public class SinglePassGroupingCollector extends SimpleCollector { if (groupMap.size() <= groupOffset) { TotalHits totalHits = new TotalHits(totalHitCount, TotalHits.Relation.EQUAL_TO); - return new TopFieldGroups(groupField, totalHits, new ScoreDoc[0], groupSort.getSort(), new Object[0]); + return new TopFieldGroups(groupField, totalHits, Lucene.EMPTY_SCORE_DOCS, groupSort.getSort(), new Object[0]); } if (orderedGroups == null) { diff --git a/server/src/main/java/org/elasticsearch/lucene/grouping/TopFieldGroups.java b/server/src/main/java/org/elasticsearch/lucene/grouping/TopFieldGroups.java index 8e5efa8a880b..350c7d91e2e4 100644 --- a/server/src/main/java/org/elasticsearch/lucene/grouping/TopFieldGroups.java +++ b/server/src/main/java/org/elasticsearch/lucene/grouping/TopFieldGroups.java @@ -16,6 +16,7 @@ import org.apache.lucene.search.SortField; import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.search.TotalHits; import org.apache.lucene.util.PriorityQueue; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.util.CollectionUtils; import java.util.ArrayList; @@ -225,7 +226,7 @@ public final class TopFieldGroups extends TopFieldDocs { queue.pop(); } } - hits = hitList.toArray(new ScoreDoc[0]); + hits = hitList.toArray(Lucene.EMPTY_SCORE_DOCS); values = groupList.toArray(new Object[0]); } TotalHits totalHits = new TotalHits(totalHitCount, totalHitsRelation); diff --git a/server/src/main/java/org/elasticsearch/search/SearchHits.java b/server/src/main/java/org/elasticsearch/search/SearchHits.java index 15b83b202fd9..b2bc3097af18 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchHits.java +++ b/server/src/main/java/org/elasticsearch/search/SearchHits.java @@ -34,7 +34,7 @@ import java.util.Objects; public final class SearchHits implements Writeable, ChunkedToXContent, RefCounted, Iterable { public static final SearchHit[] EMPTY = new SearchHit[0]; - public static final SearchHits EMPTY_WITH_TOTAL_HITS = SearchHits.empty(new TotalHits(0, Relation.EQUAL_TO), 0); + public static final SearchHits EMPTY_WITH_TOTAL_HITS = SearchHits.empty(Lucene.TOTAL_HITS_EQUAL_TO_ZERO, 0); public static final SearchHits EMPTY_WITHOUT_TOTAL_HITS = SearchHits.empty(null, 0); private final SearchHit[] hits; diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregator.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregator.java index a3cf20d0b9b7..e61465fbc5e3 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregator.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregator.java @@ -20,7 +20,6 @@ import org.apache.lucene.search.TopDocsCollector; import org.apache.lucene.search.TopFieldCollector; import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.search.TopScoreDocCollector; -import org.apache.lucene.search.TotalHits; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.search.MaxScoreCollector; import org.elasticsearch.common.lucene.Lucene; @@ -233,11 +232,7 @@ class TopHitsAggregator extends MetricsAggregator { public InternalTopHits buildEmptyAggregation() { TopDocs topDocs; if (subSearchContext.sort() != null) { - topDocs = new TopFieldDocs( - new TotalHits(0, TotalHits.Relation.EQUAL_TO), - new FieldDoc[0], - subSearchContext.sort().sort.getSort() - ); + topDocs = new TopFieldDocs(Lucene.TOTAL_HITS_EQUAL_TO_ZERO, new FieldDoc[0], subSearchContext.sort().sort.getSort()); } else { topDocs = Lucene.EMPTY_TOP_DOCS; } diff --git a/server/src/main/java/org/elasticsearch/search/query/QueryPhase.java b/server/src/main/java/org/elasticsearch/search/query/QueryPhase.java index 0d2610aa3428..af0240e9497f 100644 --- a/server/src/main/java/org/elasticsearch/search/query/QueryPhase.java +++ b/server/src/main/java/org/elasticsearch/search/query/QueryPhase.java @@ -22,7 +22,6 @@ import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.ScoreMode; import org.apache.lucene.search.Sort; import org.apache.lucene.search.TopDocs; -import org.apache.lucene.search.TotalHits; import org.apache.lucene.search.Weight; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.search.TopDocsAndMaxScore; @@ -76,11 +75,7 @@ public class QueryPhase { searchContext.size(0); QueryPhase.executeQuery(searchContext); } else { - searchContext.queryResult() - .topDocs( - new TopDocsAndMaxScore(new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), Lucene.EMPTY_SCORE_DOCS), Float.NaN), - new DocValueFormat[0] - ); + searchContext.queryResult().topDocs(new TopDocsAndMaxScore(Lucene.EMPTY_TOP_DOCS, Float.NaN), new DocValueFormat[0]); } List rrfRankResults = new ArrayList<>(); @@ -124,11 +119,7 @@ public class QueryPhase { static void executeQuery(SearchContext searchContext) throws QueryPhaseExecutionException { if (searchContext.hasOnlySuggest()) { SuggestPhase.execute(searchContext); - searchContext.queryResult() - .topDocs( - new TopDocsAndMaxScore(new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), Lucene.EMPTY_SCORE_DOCS), Float.NaN), - new DocValueFormat[0] - ); + searchContext.queryResult().topDocs(new TopDocsAndMaxScore(Lucene.EMPTY_TOP_DOCS, Float.NaN), new DocValueFormat[0]); return; } diff --git a/server/src/main/java/org/elasticsearch/search/query/QueryPhaseCollectorManager.java b/server/src/main/java/org/elasticsearch/search/query/QueryPhaseCollectorManager.java index 2286eb2e69f8..22b5f3d8dcaf 100644 --- a/server/src/main/java/org/elasticsearch/search/query/QueryPhaseCollectorManager.java +++ b/server/src/main/java/org/elasticsearch/search/query/QueryPhaseCollectorManager.java @@ -400,7 +400,7 @@ abstract class QueryPhaseCollectorManager implements CollectorManager(totalShards - skippedShards); this.isPartial = true; this.threadContext = threadContext; - this.totalHits = EMPTY_TOTAL_HITS; + this.totalHits = Lucene.TOTAL_HITS_GREATER_OR_EQUAL_TO_ZERO; this.localClusterComplete = false; } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java index 55be659512c5..dd2377ec773c 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java @@ -9,7 +9,6 @@ package org.elasticsearch.xpack.security.profile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.lucene.search.TotalHits; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.ExceptionsHelper; @@ -40,6 +39,7 @@ import org.elasticsearch.client.internal.OriginSettingClient; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.xcontent.XContentHelper; @@ -265,11 +265,7 @@ public class ProfileService { public void suggestProfile(SuggestProfilesRequest request, TaskId parentTaskId, ActionListener listener) { tryFreezeAndCheckIndex(listener.map(response -> { assert response == null : "only null response can reach here"; - return new SuggestProfilesResponse( - new SuggestProfilesResponse.ProfileHit[] {}, - 0, - new TotalHits(0, TotalHits.Relation.EQUAL_TO) - ); + return new SuggestProfilesResponse(new SuggestProfilesResponse.ProfileHit[] {}, 0, Lucene.TOTAL_HITS_EQUAL_TO_ZERO); }), SEARCH_SHARDS).ifPresent(frozenProfileIndex -> { final SearchRequest searchRequest = buildSearchRequestForSuggest(request, parentTaskId);