From b0face0735335ed961532efcd2a3c003aeb47a52 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Mon, 11 Oct 2021 08:47:12 +0200 Subject: [PATCH 01/12] Add ability to perform CCS through SQL querying This adds the ability to perform cross cluster searching through SQL. This is done by simply using the CCS-specific `cluster:index` notation, where the "cluster" maps to an SQL catalog and "index" to a table; patterns are supported for both. Noteworthy here is that a search runs either on the local or remote clusters, but not both (which is a CCS-specific behavior). Another limitation is currently that table enumeration in remote clusters will not contain aliases (not reported through field caps). Also, frozen indices are currently not listed as such (they're listed as normal indices). `SYS COLUMNS` command will not take a catalog pattern - an exact match is required -, following xDBC spec. `SYS TABLES` can, however. --- .../xpack/eql/plugin/EqlPlugin.java | 7 +- .../xpack/eql/session/EqlSession.java | 2 +- .../xpack/eql/analysis/CancellationTests.java | 6 +- .../elasticsearch/xpack/ql/index/EsIndex.java | 22 +- .../xpack/ql/index/IndexResolver.java | 227 +- .../xpack/ql/util/RemoteClusterUtils.java | 40 + .../multi-cluster-with-security/build.gradle | 55 + .../JdbcCsvSpecIT.java | 100 + .../RestSqlIT.java | 26 + .../xpack/sql/qa/jdbc/CsvSpecTestCase.java | 4 + .../sql/qa/jdbc/JdbcIntegrationTestCase.java | 14 +- .../xpack/sql/qa/jdbc/ShowTablesTestCase.java | 6 +- .../qa/jdbc/SpecBaseIntegrationTestCase.java | 13 +- .../sql/qa/rest/BaseRestSqlTestCase.java | 17 +- .../RemoteClusterAwareSqlRestTestCase.java | 97 + .../xpack/sql/qa/rest/RestSqlTestCase.java | 162 +- .../server/src/main/resources/alias.csv-spec | 110 +- .../src/main/resources/command.csv-spec | 382 ++-- .../src/main/resources/docs/docs.csv-spec | 748 +++---- .../src/main/resources/geo/geosql.csv-spec | 124 +- .../multi-cluster-command-sys.csv-spec | 224 ++ .../multi-cluster-command.csv-spec | 334 +++ .../src/main/resources/ogc/ogc.csv-spec | 4 +- .../main/resources/setup_mock_show_tables.sql | 1 + .../src/main/resources/slow/frozen.csv-spec | 18 +- x-pack/plugin/sql/src/main/antlr/SqlBase.g4 | 61 +- .../xpack/sql/analysis/analyzer/Analyzer.java | 9 +- .../xpack/sql/parser/CommandBuilder.java | 12 +- .../xpack/sql/parser/SqlBaseBaseListener.java | 12 + .../xpack/sql/parser/SqlBaseBaseVisitor.java | 7 + .../xpack/sql/parser/SqlBaseListener.java | 12 + .../xpack/sql/parser/SqlBaseParser.java | 1825 +++++++++-------- .../xpack/sql/parser/SqlBaseVisitor.java | 7 + .../plan/logical/command/ShowCatalogs.java | 61 + .../sql/plan/logical/command/ShowColumns.java | 15 +- .../sql/plan/logical/command/ShowTables.java | 21 +- .../plan/logical/command/sys/SysColumns.java | 39 +- .../plan/logical/command/sys/SysTables.java | 42 +- .../xpack/sql/plugin/SqlPlugin.java | 8 +- .../xpack/sql/session/SqlSession.java | 10 +- .../xpack/sql/analysis/CancellationTests.java | 5 +- .../xpack/sql/optimizer/OptimizerTests.java | 2 +- .../logical/command/sys/SysColumnsTests.java | 8 +- .../logical/command/sys/SysTablesTests.java | 27 +- .../xpack/sql/plugin/SqlPluginTests.java | 10 +- 45 files changed, 3156 insertions(+), 1780 deletions(-) create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java create mode 100644 x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle create mode 100644 x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java create mode 100644 x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/RestSqlIT.java create mode 100644 x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java create mode 100644 x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command-sys.csv-spec create mode 100644 x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command.csv-spec create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java index f85c9e4d03cd7..044ce3702820b 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java @@ -71,11 +71,12 @@ public Collection createComponents(Client client, ClusterService cluster ResourceWatcherService resourceWatcherService, ScriptService scriptService, NamedXContentRegistry xContentRegistry, Environment environment, NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry, IndexNameExpressionResolver expressionResolver, Supplier repositoriesServiceSupplier) { - return createComponents(client, clusterService.getClusterName().value()); + return createComponents(client, environment.settings(), clusterService); } - private Collection createComponents(Client client, String clusterName) { - IndexResolver indexResolver = new IndexResolver(client, clusterName, DefaultDataTypeRegistry.INSTANCE); + private Collection createComponents(Client client, Settings settings, ClusterService clusterService) { + IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), settings, + clusterService.getClusterSettings(), DefaultDataTypeRegistry.INSTANCE); PlanExecutor planExecutor = new PlanExecutor(client, indexResolver, circuitBreaker.get()); return Collections.singletonList(planExecutor); } diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java index ed57aed80a87a..6078d4a488584 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java @@ -107,7 +107,7 @@ private void preAnalyze(LogicalPlan parsed, ActionListener list listener.onFailure(new TaskCancelledException("cancelled")); return; } - indexResolver.resolveAsMergedMapping(indexWildcard, null, configuration.indicesOptions(), configuration.runtimeMappings(), + indexResolver.resolveAsMergedMapping(indexWildcard, configuration.indicesOptions(), configuration.runtimeMappings(), map(listener, r -> preAnalyzer.preAnalyze(parsed, r)) ); } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java index c4377d351822d..589438f992f4e 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.breaker.NoopCircuitBreaker; +import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.TaskCancelHelper; import org.elasticsearch.tasks.TaskCancelledException; @@ -138,7 +139,7 @@ public void testCancellationBeforeSearch() throws InterruptedException { }).when(client).fieldCaps(any(), any()); - IndexResolver indexResolver = new IndexResolver(client, randomAlphaOfLength(10), DefaultDataTypeRegistry.INSTANCE); + IndexResolver indexResolver = indexResolver(client); PlanExecutor planExecutor = planExecutor(client, indexResolver); CountDownLatch countDownLatch = new CountDownLatch(1); TransportEqlSearchAction.operation(planExecutor, task, new EqlSearchRequest().indices("endgame") @@ -244,6 +245,7 @@ private ClusterService mockClusterService(String nodeId) { } private static IndexResolver indexResolver(Client client) { - return new IndexResolver(client, randomAlphaOfLength(10), DefaultDataTypeRegistry.INSTANCE); + return new IndexResolver(client, randomAlphaOfLength(10), Settings.EMPTY, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), DefaultDataTypeRegistry.INSTANCE); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java index d37f696fa0dee..d6221f1f3668f 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java @@ -6,27 +6,45 @@ */ package org.elasticsearch.xpack.ql.index; +import org.elasticsearch.core.Nullable; import org.elasticsearch.xpack.ql.type.EsField; import java.util.Map; import java.util.Objects; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; + public class EsIndex { + @Nullable + private final String cluster; private final String name; private final Map mapping; public EsIndex(String name, Map mapping) { + this(null, name, mapping); + } + + public EsIndex(@Nullable String cluster, String name, Map mapping) { assert name != null; assert mapping != null; + this.cluster = cluster; this.name = name; this.mapping = mapping; } + public String cluster() { + return cluster; + } + public String name() { return name; } + public String qualifiedName() { + return buildRemoteIndexName(cluster, name); + } + public Map mapping() { return mapping; } @@ -38,7 +56,7 @@ public String toString() { @Override public int hashCode() { - return Objects.hash(name, mapping); + return Objects.hash(cluster, name, mapping); } @Override @@ -52,6 +70,6 @@ public boolean equals(Object obj) { } EsIndex other = (EsIndex) obj; - return Objects.equals(name, other.name) && mapping == other.mapping; + return Objects.equals(cluster, other.cluster) && Objects.equals(name, other.name) && mapping == other.mapping; } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java index 2c5322eea826c..d6710e7727dc3 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java @@ -11,10 +11,8 @@ import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; -import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.get.GetIndexRequest.Feature; -import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.fieldcaps.FieldCapabilities; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; @@ -25,7 +23,13 @@ import org.elasticsearch.cluster.metadata.AliasMetadata; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.core.Tuple; import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.transport.NoSuchRemoteClusterException; +import org.elasticsearch.transport.RemoteClusterAware; +import org.elasticsearch.transport.RemoteConnectionStrategy; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataTypeRegistry; @@ -55,6 +59,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.BiFunction; import java.util.function.Function; import java.util.regex.Pattern; @@ -64,11 +69,16 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static org.elasticsearch.action.ActionListener.wrap; +import static org.elasticsearch.common.Strings.hasText; +import static org.elasticsearch.common.regex.Regex.simpleMatch; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.qualifyIndices; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; public class IndexResolver { @@ -100,14 +110,20 @@ public String toNative() { } public static class IndexInfo { + private final String cluster; private final String name; private final IndexType type; - public IndexInfo(String name, IndexType type) { + public IndexInfo(String cluster, String name, IndexType type) { + this.cluster = cluster; this.name = name; this.type = type; } + public String cluster() { + return cluster; + } + public String name() { return name; } @@ -118,12 +134,12 @@ public IndexType type() { @Override public String toString() { - return name; + return buildRemoteIndexName(cluster, name); } @Override public int hashCode() { - return Objects.hash(name, type); + return Objects.hash(cluster, name, type); } @Override @@ -137,7 +153,8 @@ public boolean equals(Object obj) { } IndexResolver.IndexInfo other = (IndexResolver.IndexInfo) obj; - return Objects.equals(name, other.name) + return Objects.equals(cluster, other.cluster) + && Objects.equals(name, other.name) && Objects.equals(type, other.type); } } @@ -163,122 +180,164 @@ public boolean equals(Object obj) { private final String clusterName; private final DataTypeRegistry typeRegistry; - public IndexResolver(Client client, String clusterName, DataTypeRegistry typeRegistry) { + private final RemoteClusterResolver remoteClusters; + + public IndexResolver(Client client, String clusterName, Settings settings, ClusterSettings clusterSettings, + DataTypeRegistry typeRegistry) { this.client = client; this.clusterName = clusterName; this.typeRegistry = typeRegistry; + this.remoteClusters = new RemoteClusterResolver(settings, clusterSettings); } public String clusterName() { return clusterName; } + public Set remoteClusters() { + return new TreeSet<>(remoteClusters.clusters); + } + /** * Resolves only the names, differentiating between indices and aliases. * This method is required since the other methods rely on mapping which is tied to an index (not an alias). */ - public void resolveNames(String indexWildcard, String javaRegex, EnumSet types, ActionListener> listener) { + public void resolveNames(String clusterWildcard, String indexWildcard, String javaRegex, EnumSet types, + ActionListener> listener) { // first get aliases (if specified) boolean retrieveAliases = CollectionUtils.isEmpty(types) || types.contains(IndexType.ALIAS); boolean retrieveIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.STANDARD_INDEX); boolean retrieveFrozenIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.FROZEN_INDEX); - String[] indices = Strings.commaDelimitedListToStringArray(indexWildcard); + Set indexInfos = new HashSet<>(); if (retrieveAliases) { GetAliasesRequest aliasRequest = new GetAliasesRequest() .local(true) - .aliases(indices) + .aliases(Strings.commaDelimitedListToStringArray(indexWildcard)) .indicesOptions(IndicesOptions.lenientExpandOpen()); - client.admin().indices().getAliases(aliasRequest, wrap(aliases -> - resolveIndices(indices, javaRegex, aliases, retrieveIndices, retrieveFrozenIndices, listener), - ex -> { - // with security, two exception can be thrown: - // INFE - if no alias matches - // security exception is the user cannot access aliases - - // in both cases, that is allowed and we continue with the indices request - if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) { - resolveIndices(indices, javaRegex, null, retrieveIndices, retrieveFrozenIndices, listener); - } else { - listener.onFailure(ex); + client.admin().indices().getAliases(aliasRequest, wrap(aliases -> { + if (aliases != null) { + for (List aliasList : aliases.getAliases().values()) { + for (AliasMetadata amd : aliasList) { + String alias = amd.alias(); + if (alias != null) { + indexInfos.add(new IndexInfo(clusterName, alias, IndexType.ALIAS)); } - })); + } + } + } + resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, + listener); + }, + ex -> { + // with security, two exception can be thrown: + // INFE - if no alias matches + // security exception is the user cannot access aliases + + // in both cases, that is allowed and we continue with the indices request + if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) { + resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, + listener); + } else { + listener.onFailure(ex); + } + }) + ); } else { - resolveIndices(indices, javaRegex, null, retrieveIndices, retrieveFrozenIndices, listener); + resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, listener); } } - private void resolveIndices(String[] indices, String javaRegex, GetAliasesResponse aliases, - boolean retrieveIndices, boolean retrieveFrozenIndices, ActionListener> listener) { - + private void resolveIndices(String clusterWildcard, String indexWildcard, String javaRegex, boolean retrieveIndices, + boolean retrieveFrozenIndices, Set indexInfos, ActionListener> listener) { if (retrieveIndices || retrieveFrozenIndices) { - - GetIndexRequest indexRequest = new GetIndexRequest() + if (clusterWildcard == null || simpleMatch(clusterWildcard, clusterName)) { // resolve local indices + GetIndexRequest indexRequest = new GetIndexRequest() .local(true) - .indices(indices) + .indices(Strings.commaDelimitedListToStringArray(indexWildcard)) .features(Feature.SETTINGS) .includeDefaults(false) .indicesOptions(INDICES_ONLY_OPTIONS); - // if frozen indices are requested, make sure to update the request accordingly - if (retrieveFrozenIndices) { - indexRequest.indicesOptions(FROZEN_INDICES_OPTIONS); - } + // if frozen indices are requested, make sure to update the request accordingly + if (retrieveFrozenIndices) { + indexRequest.indicesOptions(FROZEN_INDICES_OPTIONS); + } - client.admin().indices().getIndex(indexRequest, - wrap(response -> filterResults(javaRegex, aliases, response, retrieveIndices, retrieveFrozenIndices, listener), - listener::onFailure)); + client.admin().indices().getIndex(indexRequest, wrap(indices -> { + if (indices != null) { + for (String indexName : indices.getIndices()) { + boolean isFrozen = retrieveFrozenIndices + && indices.getSettings().get(indexName).getAsBoolean("index.frozen", false); + indexInfos.add(new IndexInfo(clusterName, indexName, + isFrozen ? IndexType.FROZEN_INDEX : IndexType.STANDARD_INDEX)); + } + } + resolveRemoteIndices(clusterWildcard, indexWildcard, javaRegex, retrieveFrozenIndices, indexInfos, listener); + }, + listener::onFailure) + ); + } else { + resolveRemoteIndices(clusterWildcard, indexWildcard, javaRegex, retrieveFrozenIndices, indexInfos, listener); + } + } else { + filterResults(javaRegex, indexInfos, listener); + } + } + private void resolveRemoteIndices(String clusterWildcard, String indexWildcard, String javaRegex, boolean retrieveFrozenIndices, + Set indexInfos, ActionListener> listener) { + if (hasText(clusterWildcard)) { + IndicesOptions indicesOptions = retrieveFrozenIndices ? FIELD_CAPS_FROZEN_INDICES_OPTIONS : FIELD_CAPS_INDICES_OPTIONS; + FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(qualifyIndices(clusterWildcard, indexWildcard), indicesOptions, + emptyMap()); + client.fieldCaps(fieldRequest, wrap(response -> { + String[] indices = response.getIndices(); + if (indices != null) { + for (String indexName : indices) { + // TODO: perform two requests w/ & w/o frozen option to retrieve (by diff) the throttling status? + Tuple splitRef = splitQualifiedIndex(indexName); + String cluster = splitRef.v1() == null ? clusterName : splitRef.v1(); + indexInfos.add(new IndexInfo(cluster, splitRef.v2(), IndexType.STANDARD_INDEX)); + } + } + filterResults(javaRegex, indexInfos, listener); + }, + ex -> { + // see comment in resolveNames() + if (ex instanceof NoSuchRemoteClusterException || ex instanceof ElasticsearchSecurityException) { + filterResults(javaRegex, indexInfos, listener); + } else { + listener.onFailure(ex); + } + }) + ); } else { - filterResults(javaRegex, aliases, null, false, false, listener); + filterResults(javaRegex, indexInfos, listener); } } - private void filterResults(String javaRegex, GetAliasesResponse aliases, GetIndexResponse indices, - // these are needed to filter out the different results from the same index response - boolean retrieveIndices, - boolean retrieveFrozenIndices, - ActionListener> listener) { + private void filterResults(String javaRegex, Set indexInfos, ActionListener> listener) { // since the index name does not support ?, filter the results manually Pattern pattern = javaRegex != null ? Pattern.compile(javaRegex) : null; - Set result = new TreeSet<>(Comparator.comparing(IndexInfo::name)); - // filter aliases (if present) - if (aliases != null) { - for (List aliasList : aliases.getAliases().values()) { - for (AliasMetadata amd : aliasList) { - String alias = amd.alias(); - if (alias != null && (pattern == null || pattern.matcher(alias).matches())) { - result.add(new IndexInfo(alias, IndexType.ALIAS)); - } - } - } - } - - // filter indices (if present) - String[] indicesNames = indices != null ? indices.indices() : null; - if (indicesNames != null) { - for (String indexName : indicesNames) { - boolean isFrozen = retrieveFrozenIndices - && indices.getSettings().get(indexName).getAsBoolean("index.frozen", false); - - if (pattern == null || pattern.matcher(indexName).matches()) { - result.add(new IndexInfo(indexName, isFrozen ? IndexType.FROZEN_INDEX : IndexType.STANDARD_INDEX)); - } + Set result = new TreeSet<>(Comparator.comparing(IndexInfo::cluster).thenComparing(IndexInfo::name)); + for (IndexInfo indexInfo : indexInfos) { + if (pattern == null || pattern.matcher(indexInfo.name()).matches()) { + result.add(indexInfo); } } - listener.onResponse(result); } /** * Resolves a pattern to one (potentially compound meaning that spawns multiple indices) mapping. */ - public void resolveAsMergedMapping(String indexWildcard, String javaRegex, IndicesOptions indicesOptions, - Map runtimeMappings, ActionListener listener) { + public void resolveAsMergedMapping(String indexWildcard, IndicesOptions indicesOptions, Map runtimeMappings, + ActionListener listener) { FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, indicesOptions, runtimeMappings); client.fieldCaps(fieldRequest, ActionListener.wrap( @@ -289,8 +348,8 @@ public void resolveAsMergedMapping(String indexWildcard, String javaRegex, Indic /** * Resolves a pattern to one (potentially compound meaning that spawns multiple indices) mapping. */ - public void resolveAsMergedMapping(String indexWildcard, String javaRegex, boolean includeFrozen, Map runtimeMappings, - ActionListener listener) { + public void resolveAsMergedMapping(String indexWildcard, boolean includeFrozen, Map runtimeMappings, + ActionListener listener) { FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen, runtimeMappings); client.fieldCaps(fieldRequest, ActionListener.wrap( @@ -480,8 +539,8 @@ public void resolveAsSeparateMappings(String indexWildcard, String javaRegex, bo Map runtimeMappings, ActionListener> listener) { FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen, runtimeMappings); client.fieldCaps(fieldRequest, wrap(response -> { - client.admin().indices().getAliases(createGetAliasesRequest(response, includeFrozen), wrap(aliases -> - listener.onResponse(separateMappings(typeRegistry, javaRegex, response, aliases.getAliases())), + client.admin().indices().getAliases(createGetAliasesRequest(response, includeFrozen), wrap(aliases -> { + listener.onResponse(separateMappings(typeRegistry, javaRegex, response, aliases.getAliases()));}, ex -> { if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) { listener.onResponse(separateMappings(typeRegistry, javaRegex, response, null)); @@ -602,7 +661,8 @@ private static List buildIndices(DataTypeRegistry typeRegistry, String // put the field in their respective mappings for (String index : concreteIndices) { boolean isIndexAlias = uniqueAliases.contains(index); - if (pattern == null || pattern.matcher(index).matches() || isIndexAlias) { + // TODO is split still needed? + if (pattern == null || pattern.matcher(splitQualifiedIndex(index).v2()).matches() || isIndexAlias) { String indexName = isIndexAlias ? index : indexNameProcessor.apply(index); Fields indexFields = indices.get(indexName); if (indexFields == null) { @@ -795,4 +855,23 @@ private static Map getInvalidFieldsForAliases(String // everything checks return emptyMap(); } + + private static class RemoteClusterResolver extends RemoteClusterAware { + private final CopyOnWriteArraySet clusters; + + private RemoteClusterResolver(Settings settings, ClusterSettings clusterSettings) { + super(settings); + clusters = new CopyOnWriteArraySet<>(getEnabledRemoteClusters(settings)); + listenForUpdates(clusterSettings); + } + + @Override + protected void updateRemoteCluster(String clusterAlias, Settings settings) { + if (RemoteConnectionStrategy.isConnectionEnabled(clusterAlias, settings)) { + clusters.add(clusterAlias); + } else { + clusters.remove(clusterAlias); + } + } + } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java new file mode 100644 index 0000000000000..be11964094d48 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.ql.util; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.core.Tuple; + +import java.util.StringJoiner; + +import static org.elasticsearch.transport.RemoteClusterAware.REMOTE_CLUSTER_INDEX_SEPARATOR; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; + +public class RemoteClusterUtils { + + public static Tuple splitQualifiedIndex(String indexName) { + int separatorOffset = indexName.indexOf(REMOTE_CLUSTER_INDEX_SEPARATOR); + return separatorOffset > 0 ? Tuple.tuple(indexName.substring(0, separatorOffset), indexName.substring(separatorOffset + 1)) : + Tuple.tuple(null, indexName); + } + + public static String qualifyIndices(String cluster, String indices) { + if (cluster == null) { + return indices; + } + StringJoiner sj = new StringJoiner(","); + for (String index : Strings.commaDelimitedListToStringArray(indices)) { + sj.add(buildRemoteIndexName(cluster,index)); + } + return sj.toString(); + } + + public static boolean isQualified(String indexWildcard) { + return indexWildcard.indexOf(REMOTE_CLUSTER_INDEX_SEPARATOR) > 0; + } +} diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle new file mode 100644 index 0000000000000..675b29a9aa31a --- /dev/null +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle @@ -0,0 +1,55 @@ +import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask + +apply plugin: 'elasticsearch.internal-testclusters' +apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.rest-test' + +dependencies { + testImplementation project(path: xpackModule('eql:qa:common')) +} + +def remoteClusterReg = testClusters.register('remote-cluster') { + testDistribution = 'DEFAULT' + // numberOfNodes = 2 + setting 'node.roles', '[data,ingest,master]' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.watcher.enabled', 'false' + setting 'xpack.security.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'xpack.security.autoconfiguration.enabled', 'false' + + user username: "test_user", password: "x-pack-test-password" +} + +def integTestClusterReg = testClusters.register('integTest') { + testDistribution = 'DEFAULT' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.watcher.enabled', 'false' + setting 'cluster.remote.my_remote_cluster.seeds', { + remoteClusterReg.get().getAllTransportPortURI().collect { "\"$it\"" }.toString() + } + setting 'cluster.remote.connections_per_cluster', "1" + setting 'xpack.security.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'xpack.security.autoconfiguration.enabled', 'false' + + user username: "test_user", password: "x-pack-test-password" +} + +tasks.register("startRemoteCluster", DefaultTestClustersTask.class) { + useCluster remoteClusterReg + doLast { + "Starting remote cluster before integ tests and integTest cluster is started" + } +} + +tasks.named("integTest").configure { + dependsOn 'startRemoteCluster' + useCluster remoteClusterReg + doFirst { + nonInputProperties.systemProperty 'tests.rest.cluster.remote.host', remoteClusterReg.map(c->c.getAllHttpSocketURI().get(0)) + nonInputProperties.systemProperty 'tests.rest.cluster.remote.user', "test_user" + nonInputProperties.systemProperty 'tests.rest.cluster.remote.password', "x-pack-test-password" + } +} +tasks.named("check").configure {dependsOn("integTest") } // run these tests as part of the "check" task diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java new file mode 100644 index 0000000000000..218a731fecc65 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java @@ -0,0 +1,100 @@ +/* + * 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.sql.qa.multi_cluster_with_security; + +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.xpack.sql.qa.jdbc.CsvSpecTestCase; +import org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.CsvTestCase; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; +import static org.elasticsearch.xpack.ql.TestUtils.classpathResources; +import static org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.specParser; + +public class JdbcCsvSpecIT extends CsvSpecTestCase { + + public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; // gradle defined + public static final String EXTRACT_FN_NAME = "EXTRACT"; + + @ParametersFactory(argumentFormatting = PARAM_FORMATTING) + public static List readScriptSpec() throws Exception { + List list = new ArrayList<>(); + list.addAll(CsvSpecTestCase.readScriptSpec()); + list.addAll(readScriptSpec(classpathResources("/multi-cluster-with-security/*.csv-spec"), specParser())); + return list; + } + + public JdbcCsvSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase) { + super(fileName, groupName, testName, lineNumber, qualifyFromClause(testCase)); + } + + // qualify the query FROM clause with the cluster name, but (crudely) skip `EXTRACT(a FROM b)` calls. + private static CsvTestCase qualifyFromClause(CsvTestCase testCase) { + String query = testCase.query; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < query.length();) { + int j = query.substring(i).toUpperCase(Locale.ROOT).indexOf(EXTRACT_FN_NAME); + j = j >= 0 ? i + j : query.length(); + sb.append(query.substring(i, j).replaceAll("(?i)(FROM)(\\s+)(\\w+|\"[^\"]+\")", + "$1$2" + buildRemoteIndexName(REMOTE_CLUSTER_NAME, "$3"))); + boolean inString = false, escaping = false; + char stringDelim = 0, crrChar; + for (int k = query.indexOf('(', j + EXTRACT_FN_NAME.length()); k >= 0 && k < query.length(); k++) { + switch (crrChar = query.charAt(k)) { + case ')': + if (inString == false) { + sb.append(query, j, k + 1); + j = k + 1; + k = query.length(); + } + break; + case '"': + case '\'': + if (escaping == false) { + if (inString) { + inString = stringDelim != crrChar; + } else { + stringDelim = crrChar; + inString = true; + } + } + break; + case '\\': + if (inString) { + escaping = escaping ? false : true; // !escaping + } + break; + default: + escaping = escaping ? false : escaping; + } + } + i = j; + } + + testCase.query = sb.toString(); + return testCase; + } + + @Override + public boolean isEnabled() { + return super.isEnabled() && + // skip single-cluster tests that'd need a CLUSTER clause to work in multi-cluster mode. + (csvTestCase().query.matches("(?i)\\s*(DESCRIBE|SHOW).*") == false || fileName.startsWith("multi-cluster")); + } + + + @Override + protected int fetchSize() { + // using a smaller fetchSize for nested documents' tests to uncover bugs + // similar to https://github.com/elastic/elasticsearch/issues/35176 quicker + return fileName.startsWith("nested") && randomBoolean() ? randomIntBetween(1, 5) : super.fetchSize(); + } +} diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/RestSqlIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/RestSqlIT.java new file mode 100644 index 0000000000000..fe8ccc1a64c6a --- /dev/null +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/RestSqlIT.java @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.sql.qa.multi_cluster_with_security; + +import org.elasticsearch.xpack.sql.qa.rest.RestSqlTestCase; + +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; + +public class RestSqlIT extends RestSqlTestCase { + + public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; // gradle defined + + @Override + protected String indexPattern(String pattern) { + if (randomBoolean()) { + return buildRemoteIndexName(REMOTE_CLUSTER_NAME, pattern); + } else { + String cluster = REMOTE_CLUSTER_NAME.substring(0, randomIntBetween(0, REMOTE_CLUSTER_NAME.length())) + "*"; + return "\\\"" + buildRemoteIndexName(cluster, pattern) + "\\\""; // rest tests don't do JSON escaping + } + } +} diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/CsvSpecTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/CsvSpecTestCase.java index 6a361e9c3ab4a..f1cc36ff0a827 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/CsvSpecTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/CsvSpecTestCase.java @@ -50,6 +50,10 @@ protected final void doTest() throws Throwable { } } + public CsvTestCase csvTestCase() { + return testCase; + } + @Override protected void assertResults(ResultSet expected, ResultSet elastic) throws SQLException { Logger log = logEsResultSet() ? logger : null; diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java index 88efe11c1de43..2a5be0200e620 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java @@ -11,10 +11,10 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.core.CheckedConsumer; -import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.json.JsonXContent; import org.elasticsearch.xpack.sql.jdbc.EsDataSource; +import org.elasticsearch.xpack.sql.qa.rest.RemoteClusterAwareSqlRestTestCase; import org.junit.After; import java.io.IOException; @@ -31,12 +31,12 @@ import static org.elasticsearch.xpack.ql.TestUtils.assertNoSearchContexts; import static org.elasticsearch.xpack.sql.qa.jdbc.JdbcTestUtils.JDBC_TIMEZONE; -public abstract class JdbcIntegrationTestCase extends ESRestTestCase { +public abstract class JdbcIntegrationTestCase extends RemoteClusterAwareSqlRestTestCase { @After public void checkSearchContent() throws Exception { // Some context might linger due to fire and forget nature of scroll cleanup - assertNoSearchContexts(client()); + assertNoSearchContexts(provisioningClient()); } /** @@ -87,13 +87,13 @@ public static void index(String index, String documentId, CheckedConsumer body) throws IOException { @@ -145,7 +145,7 @@ protected static void updateMapping(String index, CheckedConsumer builder.field("name", "bob")); - h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('" + index + "', 'TABLE', 'INDEX');"); + h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('integTest', '" + index + "', 'TABLE', 'INDEX');"); } ResultSet expected = h2.createStatement().executeQuery("SELECT * FROM mock ORDER BY name"); @@ -43,8 +43,8 @@ public void testEmptyIndex() throws Exception { try (Connection h2 = LocalH2.anonymousDb(); Connection es = esJdbc()) { h2.createStatement().executeUpdate("RUNSCRIPT FROM 'classpath:/setup_mock_show_tables.sql'"); - h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('test_empty', 'TABLE', 'INDEX');"); - h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('test_empty_again', 'TABLE', 'INDEX');"); + h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('integTest', 'test_empty', 'TABLE', 'INDEX');"); + h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('integTest', 'test_empty_again', 'TABLE', 'INDEX');"); ResultSet expected = h2.createStatement().executeQuery("SELECT * FROM mock"); assertResultSets(expected, es.createStatement().executeQuery("SHOW TABLES")); diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java index c74f0790ba946..91e55a705e0b8 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java @@ -56,8 +56,8 @@ public SpecBaseIntegrationTestCase(String fileName, String groupName, String tes @Before public void setupTestDataIfNeeded() throws Exception { - if (client().performRequest(new Request("HEAD", "/" + indexName())).getStatusLine().getStatusCode() == 404) { - loadDataset(client()); + if (provisioningClient().performRequest(new Request("HEAD", "/" + indexName())).getStatusLine().getStatusCode() == 404) { + loadDataset(provisioningClient()); } } @@ -88,13 +88,17 @@ public static void wipeTestData() throws IOException { public final void test() throws Throwable { try { - assumeFalse("Test marked as Ignored", testName.endsWith("-Ignore")); + assumeTrue("Test " + testName + " is not enabled", isEnabled()); doTest(); } catch (Exception e) { throw reworkException(e); } } + public boolean isEnabled() { + return testName.endsWith("-Ignore") == false; + } + /** * Implementations should pay attention on using * {@link #executeJdbcQuery(Connection, String)} (typically for @@ -127,7 +131,8 @@ protected Properties connectionProperties() { } protected boolean logEsResultSet() { - return false; + // return false; + return true; } protected void assertResults(ResultSet expected, ResultSet elastic) throws SQLException { diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java index 82f0699446a76..40a1ff7a7a05f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java @@ -11,7 +11,6 @@ import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.xcontent.cbor.CborXContent; import org.elasticsearch.xcontent.json.JsonXContent; import org.elasticsearch.xpack.sql.proto.Mode; @@ -39,7 +38,9 @@ import static org.elasticsearch.xpack.sql.proto.Protocol.VERSION_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.WAIT_FOR_COMPLETION_TIMEOUT_NAME; -public abstract class BaseRestSqlTestCase extends ESRestTestCase { +public abstract class BaseRestSqlTestCase extends RemoteClusterAwareSqlRestTestCase { + + private static final String TEST_INDEX = "test"; public static class RequestObjectBuilder { private StringBuilder request; @@ -164,7 +165,7 @@ public String toString() { } protected void index(String... docs) throws IOException { - indexWithIndexName("test", docs); + indexWithIndexName(TEST_INDEX, docs); } protected void indexWithIndexName(String indexName, String... docs) throws IOException { @@ -176,7 +177,15 @@ protected void indexWithIndexName(String indexName, String... docs) throws IOExc bulk.append(doc + "\n"); } request.setJsonEntity(bulk.toString()); - client().performRequest(request); + provisioningClient().performRequest(request); + } + + protected void deleteTestIndex() throws IOException { + deleteIndex(TEST_INDEX); + } + + protected static void deleteIndex(String name) throws IOException { + deleteIndex(provisioningClient(), name); } public static RequestObjectBuilder query(String query) { diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java new file mode 100644 index 0000000000000..d6be513dd7666 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java @@ -0,0 +1,97 @@ +/* + * 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.sql.qa.rest; + +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.common.settings.SecureString; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.core.TimeValue; +import org.elasticsearch.core.internal.io.IOUtils; +import org.elasticsearch.test.rest.ESRestTestCase; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.io.IOException; + +import static org.elasticsearch.common.Strings.hasText; + +public abstract class RemoteClusterAwareSqlRestTestCase extends ESRestTestCase { + + private static final long CLIENT_TIMEOUT = 40L; // upped from 10s to accommodate for max measured throughput decline + + // client used for loading data on a remote cluster only. + private static RestClient remoteClient; + + @BeforeClass + public static void initRemoteClients() throws IOException { + String crossClusterHost = System.getProperty("tests.rest.cluster.remote.host"); // gradle defined + if (crossClusterHost != null) { + int portSeparator = crossClusterHost.lastIndexOf(':'); + if (portSeparator < 0) { + throw new IllegalArgumentException("Illegal cluster url [" + crossClusterHost + "]"); + } + String host = crossClusterHost.substring(0, portSeparator); + int port = Integer.parseInt(crossClusterHost.substring(portSeparator + 1)); + HttpHost[] remoteHttpHosts = new HttpHost[] { new HttpHost(host, port) }; + + remoteClient = clientBuilder(secureRemoteClientSettings(), remoteHttpHosts); + } + } + + @AfterClass + public static void closeRemoteClients() throws IOException { + try { + IOUtils.close(remoteClient); + } finally { + remoteClient = null; + } + } + + protected static RestClient clientBuilder(Settings settings, HttpHost[] hosts) throws IOException { + RestClientBuilder builder = RestClient.builder(hosts); + configureClient(builder, settings); + + int timeout = Math.toIntExact(timeout().millis()); + builder.setRequestConfigCallback( + requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .setSocketTimeout(timeout) + ); + builder.setStrictDeprecationMode(true); + return builder.build(); + } + + protected static TimeValue timeout() { + return TimeValue.timeValueSeconds(CLIENT_TIMEOUT); + } + + // returned client is used to load the test data, either in the local cluster (for rest/javaRestTests) or a remote one (for + // multi-cluster). note: the client()/adminClient() will always connect to the local cluster. + protected static RestClient provisioningClient() { + return remoteClient == null ? client() : remoteClient; + } + + @Override + protected Settings restClientSettings() { + return secureRemoteClientSettings(); + } + + protected static Settings secureRemoteClientSettings() { + // gradle defines + String user = System.getProperty("tests.rest.cluster.remote.user"); + String pass = System.getProperty("tests.rest.cluster.remote.password"); + if (hasText(user) && hasText(pass)) { + String token = basicAuthHeaderValue(user, new SecureString(pass.toCharArray())); + return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); + } + return Settings.EMPTY; + } +} diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RestSqlTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RestSqlTestCase.java index 795074084e279..4b373f63c5a74 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RestSqlTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RestSqlTestCase.java @@ -28,6 +28,7 @@ import org.elasticsearch.xpack.sql.proto.StringUtils; import org.elasticsearch.xpack.sql.qa.ErrorsTestCase; import org.hamcrest.Matcher; +import org.junit.After; import java.io.IOException; import java.io.InputStream; @@ -92,6 +93,22 @@ public static Map columnInfo(String mode, String name, String ty return unmodifiableMap(column); } + protected String indexPattern(String pattern) { + return pattern; + } + + @After + private void cleanup() throws IOException { + try { + deleteTestIndex(); + } catch (ResponseException e) { + // while the majority of tests use the index(...) test method, few create their own index + if (e.getResponse().getStatusLine().getStatusCode() != 404) { + throw e; + } + } + } + public void testBasicQuery() throws IOException { index("{\"test\":\"test\"}", "{\"test\":\"test\"}"); @@ -105,7 +122,7 @@ public void testBasicQuery() throws IOException { } else { expected.put("rows", Arrays.asList(singletonList("test"), singletonList("test"))); } - assertResponse(expected, runSql(mode, "SELECT * FROM test", columnar)); + assertResponse(expected, runSql(mode, "SELECT * FROM " + indexPattern("test"), columnar)); } public void testNextPage() throws IOException { @@ -114,9 +131,9 @@ public void testNextPage() throws IOException { String mode = randomMode(); boolean columnar = randomBoolean(); - String sqlRequest = query("SELECT text, number, SQRT(number) AS s, SCORE()" + " FROM test" + " ORDER BY number, SCORE()").mode( - mode - ).fetchSize(2).columnar(columnarValue(columnar)).toString(); + String sqlRequest = query( + "SELECT text, number, SQRT(number) AS s, SCORE() FROM " + indexPattern("test") + " ORDER BY number, SCORE()" + ).mode(mode).fetchSize(2).columnar(columnarValue(columnar)).toString(); Number value = xContentDependentFloatingNumberValue(mode, 1f); String cursor = null; @@ -200,7 +217,7 @@ public void testNextPageWithDatetimeAndTimezoneParam() throws IOException { } createIndex.endObject().endObject(); request.setJsonEntity(Strings.toString(createIndex)); - client().performRequest(request); + provisioningClient().performRequest(request); request = new Request("PUT", "/test_date_timezone/_bulk"); request.addParameter("refresh", "true"); @@ -211,11 +228,12 @@ public void testNextPageWithDatetimeAndTimezoneParam() throws IOException { bulk.append("{\"date\":").append(datetime).append("}\n"); } request.setJsonEntity(bulk.toString()); - assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); + assertEquals(200, provisioningClient().performRequest(request).getStatusLine().getStatusCode()); ZoneId zoneId = randomZone(); String mode = randomMode(); - String sqlRequest = query("SELECT DATE_PART('TZOFFSET', date) AS tz FROM test_date_timezone ORDER BY date").timeZone(zoneId.getId()) + String sqlRequest = query("SELECT DATE_PART('TZOFFSET', date) AS tz FROM " + indexPattern("test_date_timezone") + " ORDER BY date") + .timeZone(zoneId.getId()) .mode(mode) .fetchSize(2) .toString(); @@ -255,6 +273,8 @@ public void testNextPageWithDatetimeAndTimezoneParam() throws IOException { expected, runSql(new StringEntity(cursor(cursor).mode(mode).toString(), ContentType.APPLICATION_JSON), StringUtils.EMPTY, mode) ); + + deleteIndex("test_date_timezone"); } @AwaitsFix(bugUrl = "Unclear status, https://github.com/elastic/x-pack-elasticsearch/issues/2074") @@ -274,7 +294,7 @@ public void testTimeZone() throws IOException { expected.put("size", 2); // Default TimeZone is UTC - assertResponse(expected, runSql(mode, "SELECT DAY_OF_YEAR(test), COUNT(*) FROM test", columnar)); + assertResponse(expected, runSql(mode, "SELECT DAY_OF_YEAR(test), COUNT(*) FROM " + indexPattern("test"), columnar)); } public void testScoreWithFieldNamedScore() throws IOException { @@ -285,7 +305,7 @@ public void testScoreWithFieldNamedScore() throws IOException { bulk.append("{\"index\":{\"_id\":\"1\"}}\n"); bulk.append("{\"name\":\"test\", \"score\":10}\n"); request.setJsonEntity(bulk.toString()); - client().performRequest(request); + provisioningClient().performRequest(request); Map expected = new HashMap<>(); boolean columnar = randomBoolean(); @@ -304,36 +324,39 @@ public void testScoreWithFieldNamedScore() throws IOException { expected.put("rows", singletonList(Arrays.asList("test", 10, value))); } - assertResponse(expected, runSql(mode, "SELECT *, SCORE() FROM test ORDER BY SCORE()", columnar)); - assertResponse(expected, runSql(mode, "SELECT name, \\\"score\\\", SCORE() FROM test ORDER BY SCORE()", columnar)); + assertResponse(expected, runSql(mode, "SELECT *, SCORE() FROM " + indexPattern("test") + " ORDER BY SCORE()", columnar)); + assertResponse( + expected, + runSql(mode, "SELECT name, \\\"score\\\", SCORE() FROM " + indexPattern("test") + " ORDER BY SCORE()", columnar) + ); } public void testSelectWithJoinFails() throws Exception { // Normal join not supported expectBadRequest( - () -> runSql(randomMode(), "SELECT * FROM test JOIN other"), - containsString("line 1:21: Queries with JOIN are not yet supported") + () -> runSql(randomMode(), "SELECT * FROM " + indexPattern("test") + " JOIN other"), + containsString(": Queries with JOIN are not yet supported") ); // Neither is a self join expectBadRequest( - () -> runSql(randomMode(), "SELECT * FROM test JOIN test"), - containsString("line 1:21: Queries with JOIN are not yet supported") + () -> runSql(randomMode(), "SELECT * FROM " + indexPattern("test") + " JOIN test"), + containsString(": Queries with JOIN are not yet supported") ); // Nor fancy stuff like CTEs expectBadRequest( () -> runSql( randomMode(), - " WITH evil" + " AS (SELECT *" + " FROM foo)" + "SELECT *" + " FROM test" + " JOIN evil" + "WITH evil AS (SELECT * FROM " + indexPattern("foo") + ") SELECT * FROM " + indexPattern("test") + " JOIN evil" ), - containsString("line 1:67: Queries with JOIN are not yet supported") + containsString(": Queries with JOIN are not yet supported") ); } public void testSelectGroupByAllFails() throws Exception { index("{\"foo\":1}", "{\"foo\":2}"); expectBadRequest( - () -> runSql(randomMode(), "SELECT foo FROM test GROUP BY ALL foo"), - containsString("line 1:32: GROUP BY ALL is not supported") + () -> runSql(randomMode(), "SELECT foo FROM " + indexPattern("test") + " GROUP BY ALL foo"), + containsString(": GROUP BY ALL is not supported") ); } @@ -359,29 +382,32 @@ public void testSelectColumnFromMissingIndex() throws Exception { public void testSelectColumnFromEmptyIndex() throws Exception { Request request = new Request("PUT", "/test"); request.setJsonEntity("{}"); - client().performRequest(request); + provisioningClient().performRequest(request); String mode = randomFrom("jdbc", "plain"); - expectBadRequest(() -> runSql(mode, "SELECT abc FROM test"), containsString("1:8: Unknown column [abc]")); + expectBadRequest(() -> runSql(mode, "SELECT abc FROM " + indexPattern("test")), containsString("1:8: Unknown column [abc]")); } @Override public void testSelectMissingField() throws IOException { index("{\"test\":\"test\"}"); String mode = randomFrom("jdbc", "plain"); - expectBadRequest(() -> runSql(mode, "SELECT foo FROM test"), containsString("1:8: Unknown column [foo]")); + expectBadRequest(() -> runSql(mode, "SELECT foo FROM " + indexPattern("test")), containsString("1:8: Unknown column [foo]")); } @Override public void testSelectMissingFunction() throws Exception { index("{\"foo\":1}"); - expectBadRequest(() -> runSql(randomMode(), "SELECT missing(foo) FROM test"), containsString("1:8: Unknown function [missing]")); + expectBadRequest( + () -> runSql(randomMode(), "SELECT missing(foo) FROM " + indexPattern("test")), + containsString("1:8: Unknown function [missing]") + ); } @Override public void testSelectProjectScoreInAggContext() throws Exception { index("{\"foo\":1}"); expectBadRequest( - () -> runSql(randomMode(), " SELECT foo, SCORE(), COUNT(*)" + " FROM test" + " GROUP BY foo"), + () -> runSql(randomMode(), " SELECT foo, SCORE(), COUNT(*)" + " FROM " + indexPattern("test") + " GROUP BY foo"), containsString("Cannot use non-grouped column [SCORE()], expected [foo]") ); } @@ -390,7 +416,7 @@ public void testSelectProjectScoreInAggContext() throws Exception { public void testSelectOrderByScoreInAggContext() throws Exception { index("{\"foo\":1}"); expectBadRequest( - () -> runSql(randomMode(), " SELECT foo, COUNT(*)" + " FROM test" + " GROUP BY foo" + " ORDER BY SCORE()"), + () -> runSql(randomMode(), "SELECT foo, COUNT(*) FROM " + indexPattern("test") + " GROUP BY foo ORDER BY SCORE()"), containsString("Cannot order by non-grouped column [SCORE()], expected [foo]") ); } @@ -399,7 +425,7 @@ public void testSelectOrderByScoreInAggContext() throws Exception { public void testSelectGroupByScore() throws Exception { index("{\"foo\":1}"); expectBadRequest( - () -> runSql(randomMode(), "SELECT COUNT(*) FROM test GROUP BY SCORE()"), + () -> runSql(randomMode(), "SELECT COUNT(*) FROM " + indexPattern("test") + " GROUP BY SCORE()"), containsString("Cannot use [SCORE()] for grouping") ); } @@ -439,7 +465,10 @@ public void testCountAndCountDistinct() throws IOException { Map response = runSql( mode, - "SELECT gender, COUNT(langs) AS cnt, COUNT(DISTINCT langs) AS cnt_dist " + "FROM test GROUP BY gender ORDER BY gender", + "SELECT gender, COUNT(langs) AS cnt, COUNT(DISTINCT langs) AS cnt_dist " + + "FROM " + + indexPattern("test") + + " GROUP BY gender ORDER BY gender", columnar ); @@ -452,8 +481,8 @@ public void testCountAndCountDistinct() throws IOException { public void testSelectScoreSubField() throws Exception { index("{\"foo\":1}"); expectBadRequest( - () -> runSql(randomMode(), "SELECT SCORE().bar FROM test"), - containsString("line 1:15: mismatched input '.' expecting {, ") + () -> runSql(randomMode(), "SELECT SCORE().bar FROM " + indexPattern("test")), + containsString(": mismatched input '.' expecting {, ") ); } @@ -461,7 +490,7 @@ public void testSelectScoreSubField() throws Exception { public void testHardLimitForSortOnAggregate() throws Exception { index("{\"a\": 1, \"b\": 2}"); expectBadRequest( - () -> runSql(randomMode(), "SELECT max(a) max FROM test GROUP BY b ORDER BY max LIMIT 120000"), + () -> runSql(randomMode(), "SELECT max(a) max FROM " + indexPattern("test") + " GROUP BY b ORDER BY max LIMIT 120000"), containsString("The maximum LIMIT for aggregate sorting is [65536], received [120000]") ); } @@ -476,9 +505,9 @@ public void testUseColumnarForUnsupportedFormats() throws Exception { request.addParameter("format", format); request.setEntity( new StringEntity( - query("SELECT * FROM test").mode(randomValueOtherThan(Mode.JDBC.toString(), BaseRestSqlTestCase::randomMode)) - .columnar(true) - .toString(), + query("SELECT * FROM " + indexPattern("test")).mode( + randomValueOtherThan(Mode.JDBC.toString(), BaseRestSqlTestCase::randomMode) + ).columnar(true).toString(), ContentType.APPLICATION_JSON ) ); @@ -493,7 +522,12 @@ public void testUseColumnarForTranslateRequest() throws IOException { String mode = randomMode(); Request request = new Request("POST", SQL_TRANSLATE_REST_ENDPOINT); - request.setEntity(new StringEntity(query("SELECT * FROM test").mode(mode).columnar(true).toString(), ContentType.APPLICATION_JSON)); + request.setEntity( + new StringEntity( + query("SELECT * FROM " + indexPattern("test")).mode(mode).columnar(true).toString(), + ContentType.APPLICATION_JSON + ) + ); expectBadRequest(() -> { client().performRequest(request); return emptyMap(); @@ -510,7 +544,7 @@ public void testValidateRuntimeMappingsInSqlQuery() throws IOException { + "else emit(0);\"}}}"; request.setEntity( new StringEntity( - query("SELECT * FROM test").mode(mode).runtimeMappings(runtimeMappings).toString(), + query("SELECT * FROM " + indexPattern("test")).mode(mode).runtimeMappings(runtimeMappings).toString(), ContentType.APPLICATION_JSON ) ); @@ -527,7 +561,7 @@ public void testValidateRuntimeMappingsInSqlQuery() throws IOException { expected, runSql( new StringEntity( - query("SELECT * FROM test").mode(mode).runtimeMappings(runtimeMappings).toString(), + query("SELECT * FROM " + indexPattern("test")).mode(mode).runtimeMappings(runtimeMappings).toString(), ContentType.APPLICATION_JSON ), StringUtils.EMPTY, @@ -542,7 +576,9 @@ public void testValidateRuntimeMappingsInTranslateQuery() throws IOException { index("{\"test\":true}", "{\"test\":false}"); String runtimeMappings = "{\"bool_as_long\": {\"type\":\"long\", \"script\": {\"source\":\"if(doc['test'].value == true) emit(1);" + "else emit(0);\"}}}"; - Map response = runTranslateSql(query("SELECT * FROM test").runtimeMappings(runtimeMappings).toString()); + Map response = runTranslateSql( + query("SELECT * FROM " + indexPattern("test")).runtimeMappings(runtimeMappings).toString() + ); assertEquals(response.get("size"), 1000); assertFalse((Boolean) response.get("_source")); @SuppressWarnings("unchecked") @@ -556,13 +592,13 @@ public void testValidateRuntimeMappingsInTranslateQuery() throws IOException { assertEquals(singletonList(singletonMap("_doc", singletonMap("order", "asc"))), sort); } - private static void testValidateRuntimeMappingsInQuery(String queryTypeEndpoint) { + private void testValidateRuntimeMappingsInQuery(String queryTypeEndpoint) { String mode = randomMode(); String runtimeMappings = "{\"address\": {\"script\": \"return\"}}"; Request request = new Request("POST", queryTypeEndpoint); request.setEntity( new StringEntity( - query("SELECT * FROM test").mode(mode).runtimeMappings(runtimeMappings).toString(), + query("SELECT * FROM " + indexPattern("test")).mode(mode).runtimeMappings(runtimeMappings).toString(), ContentType.APPLICATION_JSON ) ); @@ -574,7 +610,7 @@ private static void testValidateRuntimeMappingsInQuery(String queryTypeEndpoint) runtimeMappings = "{\"address\": [{\"script\": \"return\"}]}"; request.setEntity( new StringEntity( - query("SELECT * FROM test").mode(mode).runtimeMappings(runtimeMappings).toString(), + query("SELECT * FROM " + indexPattern("test")).mode(mode).runtimeMappings(runtimeMappings).toString(), ContentType.APPLICATION_JSON ) ); @@ -716,7 +752,7 @@ private void executeAndAssertPrettyPrinting(String expectedJson, String prettyPa } request.setEntity( new StringEntity( - query("SELECT * FROM test").mode(Mode.PLAIN).columnar(columnarValue(columnar)).toString(), + query("SELECT * FROM " + indexPattern("test")).mode(Mode.PLAIN).columnar(columnarValue(columnar)).toString(), ContentType.APPLICATION_JSON ) ); @@ -731,7 +767,7 @@ private void executeAndAssertPrettyPrinting(String expectedJson, String prettyPa public void testBasicTranslateQuery() throws IOException { index("{\"test\":\"test\"}", "{\"test\":\"test\"}"); - Map response = runTranslateSql(query("SELECT * FROM test").toString()); + Map response = runTranslateSql(query("SELECT * FROM " + indexPattern("test")).toString()); assertEquals(1000, response.get("size")); assertFalse((Boolean) response.get("_source")); @SuppressWarnings("unchecked") @@ -750,7 +786,7 @@ public void testBasicQueryWithFilter() throws IOException { expected, runSql( new StringEntity( - query("SELECT * FROM test").mode(mode).filter("{\"match\": {\"test\": \"foo\"}}").toString(), + query("SELECT * FROM " + indexPattern("test")).mode(mode).filter("{\"match\": {\"test\": \"foo\"}}").toString(), ContentType.APPLICATION_JSON ), StringUtils.EMPTY, @@ -785,7 +821,7 @@ public void testBasicQueryWithParameters() throws IOException { expected, runSql( new StringEntity( - query("SELECT test, ? param FROM test WHERE test = ?").mode(mode) + query("SELECT test, ? param FROM " + indexPattern("test") + " WHERE test = ?").mode(mode) .columnar(columnarValue(columnar)) .params("[" + params + "]") .toString(), @@ -800,7 +836,9 @@ public void testBasicQueryWithParameters() throws IOException { public void testBasicTranslateQueryWithFilter() throws IOException { index("{\"test\":\"foo\"}", "{\"test\":\"bar\"}"); - Map response = runTranslateSql(query("SELECT * FROM test").filter("{\"match\": {\"test\": \"foo\"}}").toString()); + Map response = runTranslateSql( + query("SELECT * FROM " + indexPattern("test")).filter("{\"match\": {\"test\": \"foo\"}}").toString() + ); assertEquals(response.get("size"), 1000); assertFalse((Boolean) response.get("_source")); @@ -838,7 +876,7 @@ public void testTranslateQueryWithGroupByAndHaving() throws IOException { index("{\"salary\":100}", "{\"age\":20}"); Map response = runTranslateSql( - query("SELECT avg(salary) FROM test GROUP BY abs(age) HAVING avg(salary) > 50 LIMIT 10").toString() + query("SELECT avg(salary) FROM " + indexPattern("test") + " GROUP BY abs(age) HAVING avg(salary) > 50 LIMIT 10").toString() ); assertEquals(response.get("size"), 0); @@ -938,7 +976,7 @@ public void testBasicQueryText() throws IOException { index("{\"test\":\"test\"}", "{\"test\":\"test\"}"); String expected = " test \n" + "---------------\n" + "test \n" + "test \n"; - Tuple response = runSqlAsText("SELECT * FROM test", "text/plain"); + Tuple response = runSqlAsText("SELECT * FROM " + indexPattern("test"), "text/plain"); assertEquals(expected, response.v1()); } @@ -961,7 +999,7 @@ public void testDefaultQueryInCSV() throws IOException { String expected = "name,number\r\n" + "first,1\r\n" + "second\t,2\r\n" + "\"\"\"third,\"\"\",3\r\n"; - String query = "SELECT * FROM test ORDER BY number"; + String query = "SELECT * FROM " + indexPattern("test") + " ORDER BY number"; Tuple response = runSqlAsText(query, "text/csv"); assertEquals(expected, response.v1()); @@ -978,7 +1016,7 @@ public void testQueryWithoutHeaderInCSV() throws IOException { String expected = "first,1\r\n" + "second\t,2\r\n" + "\"\"\"third,\"\"\",3\r\n"; - String query = "SELECT * FROM test ORDER BY number"; + String query = "SELECT * FROM " + indexPattern("test") + " ORDER BY number"; Tuple response = runSqlAsText(query, "text/csv; header=absent"); assertEquals(expected, response.v1()); } @@ -989,7 +1027,7 @@ public void testNextPageCSV() throws IOException { public void testCSVWithDelimiterParameter() throws IOException { String format = randomFrom("txt", "tsv", "json", "yaml", "smile", "cbor"); - String query = "SELECT * FROM test"; + String query = "SELECT * FROM " + indexPattern("test"); index("{\"foo\":1}"); Request badRequest = new Request("POST", SQL_QUERY_REST_ENDPOINT); @@ -1025,7 +1063,7 @@ public void testQueryInTSV() throws IOException { String expected = "name\tnumber\n" + "first\t1\n" + "second\\t\t2\n" + "\"third,\"\t3\n"; - String query = "SELECT * FROM test ORDER BY number"; + String query = "SELECT * FROM " + indexPattern("test") + " ORDER BY number"; Tuple response = runSqlAsText(query, "text/tab-separated-values"); assertEquals(expected, response.v1()); response = runSqlAsTextWithFormat(query, "tsv"); @@ -1051,7 +1089,7 @@ public void testBinaryFieldFiltering() throws IOException { Request request = new Request("PUT", "/test_binary"); request.setJsonEntity(Strings.toString(createIndex)); - assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); + assertEquals(200, provisioningClient().performRequest(request).getStatusLine().getStatusCode()); long nonNullId = randomLong(); long nullId = randomLong(); @@ -1073,16 +1111,18 @@ public void testBinaryFieldFiltering() throws IOException { request = new Request("PUT", "/test_binary/_bulk?refresh=true"); request.setJsonEntity(bulk.toString()); - assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); + assertEquals(200, provisioningClient().performRequest(request).getStatusLine().getStatusCode()); String mode = randomMode(); Map expected = new HashMap<>(); expected.put("columns", singletonList(columnInfo(mode, "id", "long", JDBCType.BIGINT, 20))); expected.put("rows", singletonList(singletonList(nonNullId))); - assertResponse(expected, runSql(mode, "SELECT id FROM test_binary WHERE binary IS NOT NULL", false)); + assertResponse(expected, runSql(mode, "SELECT id FROM " + indexPattern("test_binary") + " WHERE binary IS NOT NULL", false)); expected.put("rows", singletonList(singletonList(nullId))); - assertResponse(expected, runSql(mode, "SELECT id FROM test_binary WHERE binary IS NULL", false)); + assertResponse(expected, runSql(mode, "SELECT id FROM " + indexPattern("test_binary") + " WHERE binary IS NULL", false)); + + deleteIndex("test_binary"); } private void executeQueryWithNextPage(String format, String expectedHeader, String expectedLineFormat) throws IOException { @@ -1093,7 +1133,8 @@ private void executeQueryWithNextPage(String format, String expectedHeader, Stri } index(docs); - String request = query("SELECT text, number, number + 5 AS sum FROM test ORDER BY number").fetchSize(2).toString(); + String request = query("SELECT text, number, number + 5 AS sum FROM " + indexPattern("test") + " ORDER BY number").fetchSize(2) + .toString(); String cursor = null; for (int i = 0; i < 20; i += 2) { @@ -1135,7 +1176,7 @@ private void executeQueryWithNextPage(String format, String expectedHeader, Stri ); assertEquals(true, response.get("succeeded")); - assertEquals(0, getNumberOfSearchContexts(client(), "test")); + assertEquals(0, getNumberOfSearchContexts(provisioningClient(), "test")); } private static void bulkLoadTestData(int count) throws IOException { @@ -1147,10 +1188,10 @@ private static void bulkLoadTestData(int count) throws IOException { bulk.append("{\"text\":\"text" + i + "\", \"number\":" + i + "}\n"); } request.setJsonEntity(bulk.toString()); - client().performRequest(request); + provisioningClient().performRequest(request); } - private static Tuple runSqlAsText(String sql, String accept) throws IOException { + protected static Tuple runSqlAsText(String sql, String accept) throws IOException { return runSqlAsText(StringUtils.EMPTY, new StringEntity(query(sql).toString(), ContentType.APPLICATION_JSON), accept); } @@ -1252,7 +1293,8 @@ public void testAsyncTextPaginated() throws IOException, InterruptedException { String cursor = null; for (int i = 0; i <= fetchCount; i++) { // the last iteration (the equality in `<=`) checks on no-cursor & no-results // start the query - RequestObjectBuilder builder = (hasText(cursor) ? cursor(cursor) : query("SELECT text, number FROM test")).fetchSize(fetchSize) + RequestObjectBuilder builder = (hasText(cursor) ? cursor(cursor) : query("SELECT text, number FROM " + indexPattern("test"))) + .fetchSize(fetchSize) .waitForCompletionTimeout("0d") // don't wait at all .keepOnCompletion(true) .keepAlive("1d") // keep "forever" diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec index 4244353049fb4..4178b3c20695b 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec @@ -28,82 +28,82 @@ emp_no:i | first_name:s describeAlias DESCRIBE test_alias; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describePattern DESCRIBE "test_*"; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; showAlias SHOW TABLES LIKE 'test\_alias' ESCAPE '\'; -name:s | type:s | kind:s +catalog:s |name:s | type:s | kind:s -test_alias | VIEW | ALIAS +integTest |test_alias | VIEW | ALIAS ; showPattern SHOW TABLES LIKE 'test_%'; -name:s | type:s | kind :s +catalog:s |name:s | type:s | kind :s -test_alias | VIEW | ALIAS -test_alias_emp | VIEW | ALIAS -test_emp | TABLE | INDEX -test_emp_copy | TABLE | INDEX +integTest |test_alias | VIEW | ALIAS +integTest |test_alias_emp | VIEW | ALIAS +integTest |test_emp | TABLE | INDEX +integTest |test_emp_copy | TABLE | INDEX ; groupByOnAlias diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec index c59be149efba4..de65a1c40250d 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec @@ -9,15 +9,15 @@ showFunctions SHOW FUNCTIONS; name:s | type:s -AVG |AGGREGATE +AVG |AGGREGATE COUNT |AGGREGATE FIRST |AGGREGATE FIRST_VALUE |AGGREGATE LAST |AGGREGATE LAST_VALUE |AGGREGATE MAX |AGGREGATE -MIN |AGGREGATE -SUM |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE KURTOSIS |AGGREGATE MAD |AGGREGATE PERCENTILE |AGGREGATE @@ -64,11 +64,11 @@ DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR DOM |SCALAR -DOW |SCALAR +DOW |SCALAR DOY |SCALAR FORMAT |SCALAR HOUR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR IDOW |SCALAR ISODAYOFWEEK |SCALAR ISODOW |SCALAR @@ -78,16 +78,16 @@ ISO_DAY_OF_WEEK |SCALAR ISO_WEEK_OF_YEAR |SCALAR IW |SCALAR IWOY |SCALAR -MINUTE |SCALAR -MINUTE_OF_DAY |SCALAR -MINUTE_OF_HOUR |SCALAR -MONTH |SCALAR -MONTHNAME |SCALAR -MONTH_NAME |SCALAR -MONTH_OF_YEAR |SCALAR +MINUTE |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MONTH |SCALAR +MONTHNAME |SCALAR +MONTH_NAME |SCALAR +MONTH_OF_YEAR |SCALAR NOW |SCALAR -QUARTER |SCALAR -SECOND |SCALAR +QUARTER |SCALAR +SECOND |SCALAR SECOND_OF_MINUTE |SCALAR TIMESTAMPADD |SCALAR TIMESTAMPDIFF |SCALAR @@ -97,60 +97,60 @@ TIME_PARSE |SCALAR TODAY |SCALAR TO_CHAR |SCALAR WEEK |SCALAR -WEEK_OF_YEAR |SCALAR -YEAR |SCALAR -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR -ATAN2 |SCALAR -CBRT |SCALAR -CEIL |SCALAR -CEILING |SCALAR -COS |SCALAR -COSH |SCALAR -COT |SCALAR -DEGREES |SCALAR -E |SCALAR -EXP |SCALAR -EXPM1 |SCALAR -FLOOR |SCALAR -LOG |SCALAR -LOG10 |SCALAR -MOD |SCALAR -PI |SCALAR -POWER |SCALAR -RADIANS |SCALAR -RAND |SCALAR -RANDOM |SCALAR -ROUND |SCALAR -SIGN |SCALAR -SIGNUM |SCALAR -SIN |SCALAR -SINH |SCALAR -SQRT |SCALAR -TAN |SCALAR +WEEK_OF_YEAR |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +ATAN2 |SCALAR +CBRT |SCALAR +CEIL |SCALAR +CEILING |SCALAR +COS |SCALAR +COSH |SCALAR +COT |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +MOD |SCALAR +PI |SCALAR +POWER |SCALAR +RADIANS |SCALAR +RAND |SCALAR +RANDOM |SCALAR +ROUND |SCALAR +SIGN |SCALAR +SIGNUM |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR TRUNC |SCALAR TRUNCATE |SCALAR ASCII |SCALAR -BIT_LENGTH |SCALAR -CHAR |SCALAR -CHARACTER_LENGTH |SCALAR -CHAR_LENGTH |SCALAR -CONCAT |SCALAR -INSERT |SCALAR -LCASE |SCALAR -LEFT |SCALAR -LENGTH |SCALAR -LOCATE |SCALAR -LTRIM |SCALAR -OCTET_LENGTH |SCALAR -POSITION |SCALAR -REPEAT |SCALAR -REPLACE |SCALAR -RIGHT |SCALAR -RTRIM |SCALAR -SPACE |SCALAR +BIT_LENGTH |SCALAR +CHAR |SCALAR +CHARACTER_LENGTH |SCALAR +CHAR_LENGTH |SCALAR +CONCAT |SCALAR +INSERT |SCALAR +LCASE |SCALAR +LEFT |SCALAR +LENGTH |SCALAR +LOCATE |SCALAR +LTRIM |SCALAR +OCTET_LENGTH |SCALAR +POSITION |SCALAR +REPEAT |SCALAR +REPLACE |SCALAR +RIGHT |SCALAR +RTRIM |SCALAR +SPACE |SCALAR STARTS_WITH |SCALAR SUBSTRING |SCALAR TRIM |SCALAR @@ -213,61 +213,82 @@ DAY_NAME |SCALAR DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR ISODAYOFWEEK |SCALAR ISO_DAY_OF_WEEK|SCALAR -MINUTE_OF_DAY |SCALAR +MINUTE_OF_DAY |SCALAR TODAY |SCALAR ; +showCatalogs +SHOW CATALOGS; + + name | type +---------------+--------------- +integTest |local +; + showTables SHOW TABLES; - name | type | kind -empty_mapping |TABLE |INDEX -logs |TABLE |INDEX -logs_nanos |TABLE |INDEX -test_alias |VIEW |ALIAS -test_alias_emp |VIEW |ALIAS -test_emp |TABLE |INDEX -test_emp_copy |TABLE |INDEX +catalog | name | type | kind +integTest |empty_mapping |TABLE |INDEX +integTest |logs |TABLE |INDEX +integTest |logs_nanos |TABLE |INDEX +integTest |test_alias |VIEW |ALIAS +integTest |test_alias_emp |VIEW |ALIAS +integTest |test_emp |TABLE |INDEX +integTest |test_emp_copy |TABLE |INDEX ; showTablesSimpleLike SHOW TABLES LIKE 'test_emp'; - name:s | type:s| kind:s -test_emp |TABLE |INDEX +catalog:s | name:s | type:s| kind:s +integTest |test_emp |TABLE |INDEX ; showTablesMultiLike SHOW TABLES LIKE 'test_emp%'; - name:s |type:s |kind:s -test_emp |TABLE |INDEX -test_emp_copy |TABLE |INDEX +catalog:s | name:s |type:s |kind:s +integTest |test_emp |TABLE |INDEX +integTest |test_emp_copy |TABLE |INDEX ; showTablesIdentifier SHOW TABLES "test_emp"; - name:s |type:s |kind:s -test_emp |TABLE |INDEX +catalog:s | name:s |type:s |kind:s +integTest |test_emp |TABLE |INDEX ; showTablesIdentifierPattern SHOW TABLES "test_e*,-test_emp"; - name:s |type:s |kind:s -test_emp_copy |TABLE |INDEX +catalog:s | name:s |type:s |kind:s +integTest |test_emp_copy |TABLE |INDEX ; showTablesIdentifierPatternOnAliases SHOW TABLES "test*,-test_emp*"; - name:s | type:s | kind:s -test_alias |VIEW |ALIAS -test_alias_emp |VIEW |ALIAS +catalog:s | name:s | type:s | kind:s +integTest |test_alias |VIEW |ALIAS +integTest |test_alias_emp |VIEW |ALIAS +; + +showTablesLocalCatalog +SHOW TABLES CATALOG 'integTest'; + +catalog | name | type | kind +integTest |empty_mapping |TABLE |INDEX +integTest |logs |TABLE |INDEX +integTest |logs_nanos |TABLE |INDEX +integTest |test_alias |VIEW |ALIAS +integTest |test_alias_emp |VIEW |ALIAS +integTest |test_emp |TABLE |INDEX +integTest |test_emp_copy |TABLE |INDEX ; // DESCRIBE @@ -275,87 +296,111 @@ test_alias_emp |VIEW |ALIAS describeSimpleLike DESCRIBE LIKE 'test_emp'; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describeMultiLike DESCRIBE LIKE 'test_emp%'; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describeSimpleIdentifier DESCRIBE "test_emp"; - column | type | mapping + column | type | mapping +----------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer +; + +describeSimpleIdentifierLocalCatalog +DESCRIBE CATALOG 'integTest' "test_emp"; + + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer ; @@ -364,7 +409,7 @@ salary |INTEGER |integer describeIncludeExcludeIdentifier-Ignore DESCRIBE "test_*,-test_alias*"; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- birth_date |TIMESTAMP |datetime dep |STRUCT |nested @@ -399,3 +444,28 @@ SHOW COLUMNS IN "empty_mapping"; column:s | type:s | mapping:s ----------------------+---------------+--------------- ; + +showColumnsSimpleIdentifierLocalCatalog +SHOW COLUMNS CATALOG 'integTest' IN "test_emp"; + + column | type | mapping +----------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer +; + diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec index c93c0709a6f98..ec70b9cc9102c 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec @@ -14,25 +14,25 @@ describeTable // tag::describeTable DESCRIBE emp; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword|VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer // end::describeTable ; @@ -41,7 +41,7 @@ salary |INTEGER |integer // tag::describeTableAlias //DESCRIBE employee; -// column | type +// column | type //---------------+--------------- // end::describeTableAlias @@ -49,30 +49,30 @@ salary |INTEGER |integer // // Show columns -// +// showColumns // tag::showColumns SHOW COLUMNS IN emp; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword|VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer // end::showColumns ; @@ -81,9 +81,9 @@ salary |INTEGER |integer // tag::showColumnsInAlias //SHOW COLUMNS FROM employee; -// column | type +// column | type //---------------+--------------- - + // end::showColumnsInAlias //; @@ -97,11 +97,11 @@ showTables // tag::showTables SHOW TABLES; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX -employees |VIEW |ALIAS -library |TABLE |INDEX + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX +integTest |employees |VIEW |ALIAS +integTest |library |TABLE |INDEX // end::showTables ; @@ -110,9 +110,9 @@ showTablesLikeExact // tag::showTablesLikeExact SHOW TABLES LIKE 'emp'; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX // end::showTablesLikeExact ; @@ -121,10 +121,10 @@ showTablesLikeWildcard // tag::showTablesLikeWildcard SHOW TABLES LIKE 'emp%'; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX -employees |VIEW |ALIAS + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX +integTest |employees |VIEW |ALIAS // end::showTablesLikeWildcard ; @@ -134,9 +134,9 @@ showTablesLikeOneChar // tag::showTablesLikeOneChar SHOW TABLES LIKE 'em_'; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX // end::showTablesLikeOneChar ; @@ -145,20 +145,20 @@ showTablesLikeMixed // tag::showTablesLikeMixed SHOW TABLES LIKE '%em_'; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX // end::showTablesLikeMixed ; showTablesLikeEscape -schema::name:s|type:s|kind:s +schema::catalog:s|name:s|type:s|kind:s // tag::showTablesLikeEscape SHOW TABLES LIKE 'emp!%' ESCAPE '!'; - name | type | kind ----------------+---------------+--------------- + catalog | name | type | kind +---------------+---------------+---------------+--------------- // end::showTablesLikeEscape ; @@ -168,10 +168,10 @@ showTablesEsMultiIndex // tag::showTablesEsMultiIndex SHOW TABLES "*,-l*"; - name | type | kind ----------------+----------+--------------- -emp |TABLE |INDEX -employees |VIEW |ALIAS + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |emp |TABLE |INDEX +integTest |employees |VIEW |ALIAS // end::showTablesEsMultiIndex ; @@ -184,12 +184,12 @@ showTablesIncludeFrozen // tag::showTablesIncludeFrozen SHOW TABLES INCLUDE FROZEN; - name | type | kind ----------------+----------+--------------- -archive |TABLE |FROZEN INDEX -emp |TABLE |INDEX -employees |VIEW |ALIAS -library |TABLE |INDEX + catalog | name | type | kind +---------------+---------------+----------+--------------- +integTest |archive |TABLE |FROZEN INDEX +integTest |emp |TABLE |INDEX +integTest |employees |VIEW |ALIAS +integTest |library |TABLE |INDEX // end::showTablesIncludeFrozen ; @@ -207,15 +207,15 @@ SHOW FUNCTIONS; name | type -----------------+--------------- -AVG |AGGREGATE +AVG |AGGREGATE COUNT |AGGREGATE FIRST |AGGREGATE FIRST_VALUE |AGGREGATE LAST |AGGREGATE LAST_VALUE |AGGREGATE -MAX |AGGREGATE -MIN |AGGREGATE -SUM |AGGREGATE +MAX |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE KURTOSIS |AGGREGATE MAD |AGGREGATE PERCENTILE |AGGREGATE @@ -262,11 +262,11 @@ DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR DOM |SCALAR -DOW |SCALAR +DOW |SCALAR DOY |SCALAR FORMAT |SCALAR HOUR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR IDOW |SCALAR ISODAYOFWEEK |SCALAR ISODOW |SCALAR @@ -276,16 +276,16 @@ ISO_DAY_OF_WEEK |SCALAR ISO_WEEK_OF_YEAR |SCALAR IW |SCALAR IWOY |SCALAR -MINUTE |SCALAR -MINUTE_OF_DAY |SCALAR -MINUTE_OF_HOUR |SCALAR -MONTH |SCALAR -MONTHNAME |SCALAR -MONTH_NAME |SCALAR +MINUTE |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MONTH |SCALAR +MONTHNAME |SCALAR +MONTH_NAME |SCALAR MONTH_OF_YEAR |SCALAR NOW |SCALAR -QUARTER |SCALAR -SECOND |SCALAR +QUARTER |SCALAR +SECOND |SCALAR SECOND_OF_MINUTE |SCALAR TIMESTAMPADD |SCALAR TIMESTAMPDIFF |SCALAR @@ -295,60 +295,60 @@ TIME_PARSE |SCALAR TODAY |SCALAR TO_CHAR |SCALAR WEEK |SCALAR -WEEK_OF_YEAR |SCALAR -YEAR |SCALAR -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR -ATAN2 |SCALAR -CBRT |SCALAR -CEIL |SCALAR -CEILING |SCALAR -COS |SCALAR -COSH |SCALAR -COT |SCALAR -DEGREES |SCALAR -E |SCALAR -EXP |SCALAR -EXPM1 |SCALAR -FLOOR |SCALAR -LOG |SCALAR -LOG10 |SCALAR -MOD |SCALAR -PI |SCALAR -POWER |SCALAR -RADIANS |SCALAR -RAND |SCALAR -RANDOM |SCALAR -ROUND |SCALAR -SIGN |SCALAR -SIGNUM |SCALAR -SIN |SCALAR -SINH |SCALAR -SQRT |SCALAR -TAN |SCALAR +WEEK_OF_YEAR |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +ATAN2 |SCALAR +CBRT |SCALAR +CEIL |SCALAR +CEILING |SCALAR +COS |SCALAR +COSH |SCALAR +COT |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +MOD |SCALAR +PI |SCALAR +POWER |SCALAR +RADIANS |SCALAR +RAND |SCALAR +RANDOM |SCALAR +ROUND |SCALAR +SIGN |SCALAR +SIGNUM |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR TRUNC |SCALAR TRUNCATE |SCALAR ASCII |SCALAR -BIT_LENGTH |SCALAR -CHAR |SCALAR -CHARACTER_LENGTH |SCALAR -CHAR_LENGTH |SCALAR -CONCAT |SCALAR -INSERT |SCALAR -LCASE |SCALAR -LEFT |SCALAR -LENGTH |SCALAR -LOCATE |SCALAR -LTRIM |SCALAR -OCTET_LENGTH |SCALAR -POSITION |SCALAR -REPEAT |SCALAR -REPLACE |SCALAR -RIGHT |SCALAR -RTRIM |SCALAR -SPACE |SCALAR +BIT_LENGTH |SCALAR +CHAR |SCALAR +CHARACTER_LENGTH |SCALAR +CHAR_LENGTH |SCALAR +CONCAT |SCALAR +INSERT |SCALAR +LCASE |SCALAR +LEFT |SCALAR +LENGTH |SCALAR +LOCATE |SCALAR +LTRIM |SCALAR +OCTET_LENGTH |SCALAR +POSITION |SCALAR +REPEAT |SCALAR +REPLACE |SCALAR +RIGHT |SCALAR +RTRIM |SCALAR +SPACE |SCALAR STARTS_WITH |SCALAR SUBSTRING |SCALAR TRIM |SCALAR @@ -374,9 +374,9 @@ showFunctionsLikeExact // tag::showFunctionsLikeExact SHOW FUNCTIONS LIKE 'ABS'; - name | type + name | type ---------------+--------------- -ABS |SCALAR +ABS |SCALAR // end::showFunctionsLikeExact ; @@ -385,15 +385,15 @@ showFunctionsLikeWildcard // tag::showFunctionsLikeWildcard SHOW FUNCTIONS LIKE 'A%'; - name | type + name | type ---------------+--------------- -AVG |AGGREGATE -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR +AVG |AGGREGATE +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR ATAN2 |SCALAR -ASCII |SCALAR +ASCII |SCALAR // end::showFunctionsLikeWildcard ; @@ -401,10 +401,10 @@ showFunctionsLikeChar // tag::showFunctionsLikeChar SHOW FUNCTIONS LIKE 'A__'; - name | type + name | type ---------------+--------------- -AVG |AGGREGATE -ABS |SCALAR +AVG |AGGREGATE +ABS |SCALAR // end::showFunctionsLikeChar ; @@ -412,7 +412,7 @@ showFunctionsWithPattern // tag::showFunctionsWithPattern SHOW FUNCTIONS LIKE '%DAY%'; - name | type + name | type ---------------+--------------- DAY |SCALAR DAYNAME |SCALAR @@ -423,10 +423,10 @@ DAY_NAME |SCALAR DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR ISODAYOFWEEK |SCALAR ISO_DAY_OF_WEEK|SCALAR -MINUTE_OF_DAY |SCALAR +MINUTE_OF_DAY |SCALAR TODAY |SCALAR // end::showFunctionsWithPattern @@ -442,9 +442,9 @@ selectColumnAlias // tag::selectColumnAlias SELECT 1 + 1 AS result; - result + result --------------- -2 +2 // end::selectColumnAlias ; @@ -453,9 +453,9 @@ selectInline // tag::selectInline SELECT 1 + 1; - 1 + 1 + 1 + 1 -------------- -2 +2 // end::selectInline ; @@ -464,9 +464,9 @@ selectColumn // tag::selectColumn SELECT emp_no FROM emp LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::selectColumn ; @@ -475,9 +475,9 @@ selectQualifiedColumn // tag::selectQualifiedColumn SELECT emp.emp_no FROM emp LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::selectQualifiedColumn ; @@ -487,7 +487,7 @@ wildcardWithOrder // tag::wildcardWithOrder SELECT * FROM emp LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 @@ -498,10 +498,10 @@ fromTable // tag::fromTable SELECT * FROM emp LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 - + // end::fromTable ; @@ -510,7 +510,7 @@ fromTableQuoted // tag::fromTableQuoted SELECT * FROM "emp" LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 @@ -521,7 +521,7 @@ fromTableIncludeFrozen // tag::fromTableIncludeFrozen SELECT * FROM FROZEN archive LIMIT 1; - author | name | page_count | release_date + author | name | page_count | release_date -----------------+--------------------+---------------+-------------------- James S.A. Corey |Leviathan Wakes |561 |2011-06-02T00:00:00Z @@ -532,9 +532,9 @@ fromTableQuoted // tag::fromTablePatternQuoted SELECT emp_no FROM "e*p" LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::fromTablePatternQuoted ; @@ -543,9 +543,9 @@ fromTableAlias // tag::fromTableAlias SELECT e.emp_no FROM emp AS e LIMIT 1; - emp_no + emp_no ------------- -10001 +10001 // end::fromTableAlias ; @@ -554,9 +554,9 @@ basicWhere // tag::basicWhere SELECT last_name FROM emp WHERE emp_no = 10001; - last_name + last_name --------------- -Facello +Facello // end::basicWhere ; @@ -572,7 +572,7 @@ schema::g:s // tag::groupByColumn SELECT gender AS g FROM emp GROUP BY gender; - g + g --------------- null F @@ -586,11 +586,11 @@ schema::gender:s // tag::groupByOrdinal SELECT gender FROM emp GROUP BY 1; - gender + gender --------------- null -F -M +F +M // end::groupByOrdinal ; @@ -600,11 +600,11 @@ schema::g:s // tag::groupByAlias SELECT gender AS g FROM emp GROUP BY g; - g + g --------------- null -F -M +F +M // end::groupByAlias ; @@ -613,15 +613,15 @@ groupByExpression // tag::groupByExpression SELECT languages + 1 AS l FROM emp GROUP BY l; - l + l --------------- null -2 -3 -4 -5 -6 - +2 +3 +4 +5 +6 + // end::groupByExpression ; @@ -631,24 +631,24 @@ schema::g:s|l:i|c:l // tag::groupByMulti SELECT gender g, languages l, COUNT(*) c FROM "emp" GROUP BY g, l ORDER BY languages ASC, gender DESC; - g | l | c + g | l | c ---------------+---------------+--------------- -M |null |7 -F |null |3 -M |1 |9 -F |1 |4 -null |1 |2 -M |2 |11 -F |2 |5 -null |2 |3 -M |3 |11 -F |3 |6 -M |4 |11 -F |4 |6 -null |4 |1 -M |5 |8 -F |5 |9 -null |5 |4 +M |null |7 +F |null |3 +M |1 |9 +F |1 |4 +null |1 |2 +M |2 |11 +F |2 |5 +null |2 |3 +M |3 |11 +F |3 |6 +M |4 |11 +F |4 |6 +null |4 |1 +M |5 |8 +F |5 |9 +null |5 |4 // end::groupByMulti @@ -660,11 +660,11 @@ schema::g:s|c:i // tag::groupByAndAgg SELECT gender AS g, COUNT(*) AS c FROM emp GROUP BY gender; - g | c + g | c ---------------+--------------- -null |10 -F |33 -M |57 +null |10 +F |33 +M |57 // end::groupByAndAgg ; @@ -674,7 +674,7 @@ schema::g:s|salary:i // tag::groupByAndAggExpression SELECT gender AS g, ROUND((MIN(salary) / 100)) AS salary FROM emp GROUP BY gender; - g | salary + g | salary ---------------+--------------- null |253 F |259 @@ -687,11 +687,11 @@ schema::g:s|k:d|s:d // tag::groupByAndMultipleAggs SELECT gender AS g, KURTOSIS(salary) AS k, SKEWNESS(salary) AS s FROM emp GROUP BY gender; - g | k | s + g | k | s ---------------+------------------+------------------- null |2.2215791166941923|-0.03373126000214023 -F |1.7873117044424276|0.05504995122217512 -M |2.280646181070106 |0.44302407229580243 +F |1.7873117044424276|0.05504995122217512 +M |2.280646181070106 |0.44302407229580243 // end::groupByAndMultipleAggs @@ -701,9 +701,9 @@ groupByImplicitCount // tag::groupByImplicitCount SELECT COUNT(*) AS count FROM emp; - count + count --------------- -100 +100 // end::groupByImplicitCount ; @@ -718,12 +718,12 @@ groupByHaving // tag::groupByHaving SELECT languages AS l, COUNT(*) AS c FROM emp GROUP BY l HAVING c BETWEEN 15 AND 20; - l | c + l | c ---------------+--------------- -1 |15 -2 |19 -3 |17 -4 |18 +1 |15 +2 |19 +3 |17 +4 |18 // end::groupByHaving ; @@ -732,14 +732,14 @@ groupByHavingMultiple // tag::groupByHavingMultiple SELECT MIN(salary) AS min, MAX(salary) AS max, MAX(salary) - MIN(salary) AS diff FROM emp GROUP BY languages HAVING diff - max % min > 0 AND AVG(salary) > 30000; - min | max | diff + min | max | diff ---------------+---------------+--------------- -28336 |74999 |46663 -25976 |73717 |47741 -29175 |73578 |44403 -26436 |74970 |48534 -27215 |74572 |47357 -25324 |66817 |41493 +28336 |74999 |46663 +25976 |73717 |47741 +29175 |73578 |44403 +26436 |74970 |48534 +27215 |74572 |47357 +25324 |66817 |41493 // end::groupByHavingMultiple @@ -749,9 +749,9 @@ groupByImplicitMultipleAggs // tag::groupByImplicitMultipleAggs SELECT MIN(salary) AS min, MAX(salary) AS max, AVG(salary) AS avg, COUNT(*) AS count FROM emp; - min:i | max:i | avg:d | count:l + min:i | max:i | avg:d | count:l ---------------+---------------+---------------+--------------- -25324 |74999 |48248.55 |100 +25324 |74999 |48248.55 |100 // end::groupByImplicitMultipleAggs ; @@ -760,9 +760,9 @@ groupByHavingImplicitMatch // tag::groupByHavingImplicitMatch SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING min > 25000; - min | max + min | max ---------------+--------------- -25324 |74999 +25324 |74999 // end::groupByHavingImplicitMatch ; @@ -771,7 +771,7 @@ SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING min > 25000; // tag::groupByHavingImplicitNoMatch //SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING max > 75000; -// min | max +// min | max //---------------+--------------- // end::groupByHavingImplicitNoMatch @@ -789,20 +789,20 @@ histogramNumeric // tag::histogramNumeric SELECT HISTOGRAM(salary, 5000) AS h FROM emp GROUP BY h; - h ---------------- -25000 -30000 -35000 -40000 -45000 -50000 -55000 -60000 -65000 + h +--------------- +25000 +30000 +35000 +40000 +45000 +50000 +55000 +60000 +65000 70000 -// end::histogramNumeric +// end::histogramNumeric ; histogramNumericExpression @@ -810,20 +810,20 @@ schema::h:i|c:l // tag::histogramNumericExpression SELECT HISTOGRAM(salary % 100, 10) AS h, COUNT(*) AS c FROM emp GROUP BY h; - h | c + h | c ---------------+--------------- -0 |10 -10 |15 -20 |10 -30 |14 -40 |9 -50 |9 -60 |8 -70 |13 -80 |3 -90 |9 +0 |10 +10 |15 +20 |10 +30 |14 +40 |9 +50 |9 +60 |8 +70 |13 +80 |3 +90 |9 -// end::histogramNumericExpression +// end::histogramNumericExpression ; histogramDateTime @@ -832,23 +832,23 @@ schema::h:ts|c:l SELECT HISTOGRAM(birth_date, INTERVAL 1 YEAR) AS h, COUNT(*) AS c FROM emp GROUP BY h; - h | c + h | c ------------------------+--------------- -null |10 -1952-01-01T00:00:00.000Z|8 -1953-01-01T00:00:00.000Z|11 -1954-01-01T00:00:00.000Z|8 -1955-01-01T00:00:00.000Z|4 -1956-01-01T00:00:00.000Z|5 -1957-01-01T00:00:00.000Z|4 -1958-01-01T00:00:00.000Z|7 -1959-01-01T00:00:00.000Z|9 -1960-01-01T00:00:00.000Z|8 -1961-01-01T00:00:00.000Z|8 -1962-01-01T00:00:00.000Z|6 -1963-01-01T00:00:00.000Z|7 -1964-01-01T00:00:00.000Z|4 -1965-01-01T00:00:00.000Z|1 +null |10 +1952-01-01T00:00:00.000Z|8 +1953-01-01T00:00:00.000Z|11 +1954-01-01T00:00:00.000Z|8 +1955-01-01T00:00:00.000Z|4 +1956-01-01T00:00:00.000Z|5 +1957-01-01T00:00:00.000Z|4 +1958-01-01T00:00:00.000Z|7 +1959-01-01T00:00:00.000Z|9 +1960-01-01T00:00:00.000Z|8 +1961-01-01T00:00:00.000Z|8 +1962-01-01T00:00:00.000Z|6 +1963-01-01T00:00:00.000Z|7 +1964-01-01T00:00:00.000Z|4 +1965-01-01T00:00:00.000Z|1 // end::histogramDateTime ; @@ -863,16 +863,16 @@ schema::h:i|c:l // tag::histogramDateTimeExpression SELECT HISTOGRAM(MONTH(birth_date), 2) AS h, COUNT(*) as c FROM emp GROUP BY h ORDER BY h DESC; - h | c + h | c ---------------+--------------- -12 |7 -10 |17 -8 |16 -6 |16 -4 |18 -2 |10 -0 |6 -null |10 +12 |7 +10 |17 +8 |16 +6 |16 +4 |18 +2 |10 +0 |6 +null |10 // end::histogramDateTimeExpression ; @@ -925,7 +925,7 @@ dtDateTimePlusInterval // tag::dtDateTimePlusInterval SELECT CAST('1969-05-13T12:34:56' AS DATETIME) + INTERVAL 49 YEARS AS result; - result + result -------------------- 2018-05-13T12:34:56Z // end::dtDateTimePlusInterval @@ -935,9 +935,9 @@ dtMinusInterval // tag::dtMinusInterval SELECT - INTERVAL '49-1' YEAR TO MONTH result; - result + result --------------- --49-1 +-49-1 // end::dtMinusInterval ; @@ -957,7 +957,7 @@ dtDateTimeMinusInterval // tag::dtDateTimeMinusInterval SELECT CAST('2018-05-13T12:34:56' AS DATETIME) - INTERVAL '2-8' YEAR TO MONTH AS result; - result + result -------------------- 2015-09-13T12:34:56Z // end::dtDateTimeMinusInterval @@ -967,9 +967,9 @@ dtIntervalMul // tag::dtIntervalMul SELECT -2 * INTERVAL '3' YEARS AS result; - result + result --------------- --6-0 +-6-0 // end::dtIntervalMul ; @@ -984,7 +984,7 @@ orderByBasic // tag::orderByBasic SELECT * FROM library ORDER BY page_count DESC LIMIT 5; - author | name | page_count | release_date + author | name | page_count | release_date -----------------+--------------------+---------------+-------------------- Peter F. Hamilton|Pandora's Star |768 |2004-03-02T00:00:00Z Vernor Vinge |A Fire Upon the Deep|613 |1992-06-01T00:00:00Z @@ -1000,12 +1000,12 @@ schema::g:s|c:i // tag::orderByGroup SELECT gender AS g, COUNT(*) AS c FROM emp GROUP BY gender ORDER BY g DESC; - g | c + g | c ---------------+--------------- M |57 -F |33 -null |10 - +F |33 +null |10 + // end::orderByGroup ; @@ -1014,12 +1014,12 @@ schema::g:s|salary:i // tag::orderByAgg SELECT gender AS g, MIN(salary) AS salary FROM emp GROUP BY gender ORDER BY salary DESC; - g | salary + g | salary ---------------+--------------- -F |25976 -M |25945 -null |25324 - +F |25976 +M |25945 +null |25324 + // end::orderByAgg ; @@ -1106,7 +1106,7 @@ orderByScore // tag::orderByScore SELECT SCORE(), * FROM library WHERE MATCH(name, 'dune') ORDER BY SCORE() DESC; - SCORE() | author | name | page_count | release_date + SCORE() | author | name | page_count | release_date ---------------+---------------+-------------------+---------------+-------------------- 2.2886353 |Frank Herbert |Dune |604 |1965-06-01T00:00:00Z 1.8893257 |Frank Herbert |Dune Messiah |331 |1969-10-15T00:00:00Z @@ -1120,7 +1120,7 @@ orderByScoreWithMatch // tag::orderByScoreWithMatch SELECT SCORE(), * FROM library WHERE MATCH(name, 'dune') ORDER BY page_count DESC; - SCORE() | author | name | page_count | release_date + SCORE() | author | name | page_count | release_date ---------------+---------------+-------------------+---------------+-------------------- 2.2886353 |Frank Herbert |Dune |604 |1965-06-01T00:00:00Z 1.4005898 |Frank Herbert |God Emperor of Dune|454 |1981-05-28T00:00:00Z @@ -1134,7 +1134,7 @@ scoreWithMatch // tag::scoreWithMatch SELECT SCORE() AS score, name, release_date FROM library WHERE QUERY('dune') ORDER BY YEAR(release_date) DESC; - score | name | release_date + score | name | release_date ---------------+-------------------+-------------------- 1.4005898 |God Emperor of Dune|1981-05-28T00:00:00Z 1.6086556 |Children of Dune |1976-04-21T00:00:00Z @@ -1154,9 +1154,9 @@ limitBasic // tag::limitBasic SELECT first_name, last_name, emp_no FROM emp LIMIT 1; - first_name | last_name | emp_no + first_name | last_name | emp_no ---------------+---------------+--------------- -Georgi |Facello |10001 +Georgi |Facello |10001 // end::limitBasic ; @@ -1205,9 +1205,9 @@ aggCountStar // tag::aggCountStar SELECT COUNT(*) AS count FROM emp; - count + count --------------- -100 +100 // end::aggCountStar ; @@ -1215,9 +1215,9 @@ aggCountAll // tag::aggCountAll SELECT COUNT(ALL last_name) AS count_all, COUNT(DISTINCT last_name) count_distinct FROM emp; - count_all | count_distinct + count_all | count_distinct ---------------+------------------ -100 |96 +100 |96 // end::aggCountAll ; @@ -1416,9 +1416,9 @@ aggMax // tag::aggMax SELECT MAX(salary) AS max FROM emp; - max + max --------------- -74999 +74999 // end::aggMax ; @@ -1437,9 +1437,9 @@ aggMin // tag::aggMin SELECT MIN(salary) AS min FROM emp; - min + min --------------- -25324 +25324 // end::aggMin ; @@ -1479,7 +1479,7 @@ aggKurtosis // tag::aggKurtosis SELECT MIN(salary) AS min, MAX(salary) AS max, KURTOSIS(salary) AS k FROM emp; - min | max | k + min | max | k ---------------+---------------+------------------ 25324 |74999 |2.0444718929142986 // end::aggKurtosis @@ -1489,9 +1489,9 @@ aggMad // tag::aggMad SELECT MIN(salary) AS min, MAX(salary) AS max, AVG(salary) AS avg, MAD(salary) AS mad FROM emp; - min | max | avg | mad + min | max | avg | mad ---------------+---------------+---------------+--------------- -25324 |74999 |48248.55 |10096.5 +25324 |74999 |48248.55 |10096.5 // end::aggMad ; @@ -1508,17 +1508,17 @@ SELECT MIN(salary / 12.0) AS min, MAX(salary / 12.0) AS max, AVG(salary/ 12.0) A aggPercentile // tag::aggPercentile -SELECT languages, PERCENTILE(salary, 95) AS "95th" FROM emp +SELECT languages, PERCENTILE(salary, 95) AS "95th" FROM emp GROUP BY languages; - languages | 95th + languages | 95th ---------------+----------------- -null |74999.0 -1 |72790.5 +null |74999.0 +1 |72790.5 2 |71924.70000000001 -3 |73638.25 +3 |73638.25 4 |72115.59999999999 -5 |61071.7 +5 |61071.7 // end::aggPercentile ; @@ -1542,20 +1542,20 @@ null |6249.916666666667 aggPercentileWithPercentileConfig // tag::aggPercentileWithPercentileConfig SELECT - languages, - PERCENTILE(salary, 97.3, 'tdigest', 100.0) AS "97.3_TDigest", - PERCENTILE(salary, 97.3, 'hdr', 3) AS "97.3_HDR" -FROM emp + languages, + PERCENTILE(salary, 97.3, 'tdigest', 100.0) AS "97.3_TDigest", + PERCENTILE(salary, 97.3, 'hdr', 3) AS "97.3_HDR" +FROM emp GROUP BY languages; - languages | 97.3_TDigest | 97.3_HDR + languages | 97.3_TDigest | 97.3_HDR ---------------+---------------+--------------- -null |74999.0 |74992.0 -1 |73717.0 |73712.0 -2 |73530.238 |69936.0 -3 |74970.0 |74992.0 -4 |74572.0 |74608.0 -5 |66117.118 |56368.0 +null |74999.0 |74992.0 +1 |73717.0 |73712.0 +2 |73530.238 |69936.0 +3 |74970.0 |74992.0 +4 |74572.0 |74608.0 +5 |66117.118 |56368.0 // end::aggPercentileWithPercentileConfig ; @@ -1563,14 +1563,14 @@ aggPercentileRank // tag::aggPercentileRank SELECT languages, PERCENTILE_RANK(salary, 65000) AS rank FROM emp GROUP BY languages; - languages | rank + languages | rank ---------------+----------------- null |73.65766569962062 -1 |73.7291625157734 +1 |73.7291625157734 2 |88.88005607010643 3 |79.43662623295829 4 |85.70446389643493 -5 |100.0 +5 |100.0 // end::aggPercentileRank ; @@ -1599,14 +1599,14 @@ SELECT FROM emp GROUP BY languages; - languages | rank_TDigest | rank_HDR + languages | rank_TDigest | rank_HDR ---------------+---------------+--------------- -null |73.66 |80.0 -1 |73.73 |73.33 -2 |88.88 |89.47 -3 |79.44 |76.47 -4 |85.7 |83.33 -5 |100.0 |95.24 +null |73.66 |80.0 +1 |73.73 |73.33 +2 |88.88 |89.47 +3 |79.44 |76.47 +4 |85.7 |83.33 +5 |100.0 |95.24 // end::aggPercentileRankWithPercentileConfig ; @@ -1614,7 +1614,7 @@ aggSkewness // tag::aggSkewness SELECT MIN(salary) AS min, MAX(salary) AS max, SKEWNESS(salary) AS s FROM emp; - min | max | s + min | max | s ---------------+---------------+------------------ 25324 |74999 |0.2707722118423227 // end::aggSkewness @@ -1665,10 +1665,10 @@ SELECT MIN(salary / 12.0) AS min, MAX(salary / 12.0) AS max, STDDEV_SAMP(salary aggSumOfSquares // tag::aggSumOfSquares -SELECT MIN(salary) AS min, MAX(salary) AS max, SUM_OF_SQUARES(salary) AS sumsq +SELECT MIN(salary) AS min, MAX(salary) AS max, SUM_OF_SQUARES(salary) AS sumsq FROM emp; - min | max | sumsq + min | max | sumsq ---------------+---------------+---------------- 25324 |74999 |2.51740125721E11 // end::aggSumOfSquares @@ -1689,7 +1689,7 @@ aggVarPop // tag::aggVarPop SELECT MIN(salary) AS min, MAX(salary) AS max, VAR_POP(salary) AS varpop FROM emp; - min | max | varpop + min | max | varpop ---------------+---------------+---------------- 25324 |74999 |1.894786801075E8 // end::aggVarPop @@ -1738,9 +1738,9 @@ stringAscii // tag::stringAscii SELECT ASCII('Elastic'); -ASCII('Elastic') +ASCII('Elastic') ---------------- -69 +69 // end::stringAscii ; @@ -1750,7 +1750,7 @@ SELECT BIT_LENGTH('Elastic'); BIT_LENGTH('Elastic') --------------------- -56 +56 // end::stringBitLength ; @@ -1758,9 +1758,9 @@ stringChar // tag::stringChar SELECT CHAR(69); - CHAR(69) + CHAR(69) --------------- -E +E // end::stringChar ; @@ -1770,7 +1770,7 @@ SELECT CHAR_LENGTH('Elastic'); CHAR_LENGTH('Elastic') ---------------------- -7 +7 // end::stringCharLength ; @@ -1780,7 +1780,7 @@ SELECT CONCAT('Elasticsearch', ' SQL'); CONCAT('Elasticsearch', ' SQL') ------------------------------- -Elasticsearch SQL +Elasticsearch SQL // end::stringConcat ; @@ -1800,7 +1800,7 @@ SELECT LCASE('Elastic'); LCASE('Elastic') ---------------- -elastic +elastic // end::stringLCase ; @@ -1810,7 +1810,7 @@ SELECT LEFT('Elastic',3); LEFT('Elastic',3) ----------------- -Ela +Ela // end::stringLeft ; @@ -1820,7 +1820,7 @@ SELECT LENGTH('Elastic '); LENGTH('Elastic ') -------------------- -7 +7 // end::stringLength ; @@ -1830,7 +1830,7 @@ SELECT LOCATE('a', 'Elasticsearch'); LOCATE('a', 'Elasticsearch') ---------------------------- -3 +3 // end::stringLocateWoStart ; @@ -1850,7 +1850,7 @@ SELECT LTRIM(' Elastic'); LTRIM(' Elastic') ------------------- -Elastic +Elastic // end::stringLTrim ; @@ -1860,7 +1860,7 @@ SELECT OCTET_LENGTH('Elastic'); OCTET_LENGTH('Elastic') ----------------------- -7 +7 // end::stringOctetLength ; @@ -1870,7 +1870,7 @@ SELECT POSITION('Elastic', 'Elasticsearch'); POSITION('Elastic', 'Elasticsearch') ------------------------------------ -1 +1 // end::stringPosition ; @@ -1878,9 +1878,9 @@ stringRepeat // tag::stringRepeat SELECT REPEAT('La', 3); - REPEAT('La', 3) + REPEAT('La', 3) ---------------- -LaLaLa +LaLaLa // end::stringRepeat ; @@ -1900,7 +1900,7 @@ SELECT RIGHT('Elastic',3); RIGHT('Elastic',3) ------------------ -tic +tic // end::stringRight ; @@ -1910,7 +1910,7 @@ SELECT RTRIM('Elastic '); RTRIM('Elastic ') ------------------- -Elastic +Elastic // end::stringRTrim ; @@ -1919,10 +1919,10 @@ schema::SPACE(3):s // tag::stringSpace SELECT SPACE(3); - SPACE(3) + SPACE(3) --------------- - - + + // end::stringSpace ; @@ -1932,7 +1932,7 @@ SELECT STARTS_WITH('Elasticsearch', 'Elastic'); STARTS_WITH('Elasticsearch', 'Elastic') -------------------------------- -true +true // end::stringStartsWithTrue ; @@ -1942,7 +1942,7 @@ SELECT STARTS_WITH('Elasticsearch', 'ELASTIC'); STARTS_WITH('Elasticsearch', 'ELASTIC') -------------------------------- -false +false // end::stringStartsWithFalse ; @@ -1952,7 +1952,7 @@ SELECT SUBSTRING('Elasticsearch', 0, 7); SUBSTRING('Elasticsearch', 0, 7) -------------------------------- -Elastic +Elastic // end::stringSubString ; @@ -1970,9 +1970,9 @@ stringUCase // tag::stringUCase SELECT UCASE('Elastic'); -UCASE('Elastic') +UCASE('Elastic') ---------------- -ELASTIC +ELASTIC // end::stringUCase ; @@ -1987,9 +1987,9 @@ conversionStringToIntCast // tag::conversionStringToIntCast SELECT CAST('123' AS INT) AS int; - int + int --------------- -123 +123 // end::conversionStringToIntCast ; @@ -1998,9 +1998,9 @@ schema::string:s // tag::conversionIntToStringCast SELECT CAST(123 AS VARCHAR) AS string; - string + string --------------- -123 +123 // end::conversionIntToStringCast ; @@ -3416,7 +3416,7 @@ currentTimestamp-Ignore // tag::curTs SELECT CURRENT_TIMESTAMP AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::curTs @@ -3426,7 +3426,7 @@ currentTimestampFunction-Ignore // tag::curTsFunction SELECT CURRENT_TIMESTAMP() AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::curTsFunction @@ -3436,7 +3436,7 @@ currentTimestampFunctionPrecision-Ignore // tag::curTsFunctionPrecision SELECT CURRENT_TIMESTAMP(1) AS result; - result + result ------------------------ 2018-12-12T14:48:52.4Z // end::curTsFunctionPrecision @@ -3447,7 +3447,7 @@ nowFunction-Ignore // tag::nowFunction SELECT NOW() AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::nowFunction diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec index 391f0effc6154..090baaaf54cdf 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec @@ -7,8 +7,8 @@ showTables SHOW TABLES "geo"; - name:s | type:s| kind:s -geo |TABLE |INDEX + catalog:s | name:s | type:s| kind:s +integTest |geo |TABLE |INDEX ; // DESCRIBE @@ -33,21 +33,21 @@ selectAllPointsAsStrings SELECT city, CAST(location AS STRING) location, CAST(location_no_dv AS STRING) location_no_dv, CAST(geoshape AS STRING) geoshape, CAST(shape AS STRING) shape, region FROM "geo" ORDER BY "city"; city:s | location:s | location_no_dv:s | geoshape:s | shape:s | region:s -Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |POINT (4.850312 52.347557 2.0) |Europe -Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |POINT (13.390889 52.486701 34.0) |Europe -Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |POINT (-87.637874 41.888783 181.0) |Americas -Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |POINT (114.183925 22.281397 552.0) |Asia -London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |POINT (-0.121672 51.510871 11.0) |Europe -Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |POINT (-122.083843 37.386483 30.0) |Americas -Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |POINT (11.537505 48.146321 519.0) |Europe -New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |POINT (-73.990027 40.745171 10.0) |Americas -Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |POINT (2.351773 48.845538 35.0) |Europe -Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|POINT (-111.973505 33.376242 331.0)|Americas -San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |POINT (-122.394228 37.789541 16.0) |Americas -Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |POINT (127.060851 37.509132 38.0) |Asia -Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |POINT (103.855535 1.295868 15.0) |Asia -Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|POINT (151.208629 -33.863385 100.0)|Asia -Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|POINT (139.76402225 35.669616 40.0)|Asia +Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |POINT (4.850312 52.347557 2.0) |Europe +Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |POINT (13.390889 52.486701 34.0) |Europe +Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |POINT (-87.637874 41.888783 181.0) |Americas +Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |POINT (114.183925 22.281397 552.0) |Asia +London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |POINT (-0.121672 51.510871 11.0) |Europe +Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |POINT (-122.083843 37.386483 30.0) |Americas +Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |POINT (11.537505 48.146321 519.0) |Europe +New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |POINT (-73.990027 40.745171 10.0) |Americas +Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |POINT (2.351773 48.845538 35.0) |Europe +Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|POINT (-111.973505 33.376242 331.0)|Americas +San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |POINT (-122.394228 37.789541 16.0) |Americas +Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |POINT (127.060851 37.509132 38.0) |Asia +Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |POINT (103.855535 1.295868 15.0) |Asia +Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|POINT (151.208629 -33.863385 100.0)|Asia +Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|POINT (139.76402225 35.669616 40.0)|Asia ; // TODO: Both shape and location contain the same data for now, we should change it later to make things more interesting @@ -55,49 +55,49 @@ selectAllPointsAsWKT SELECT city, ST_ASWKT(location) location_wkt, ST_ASWKT(geoshape) geoshape_wkt, region FROM "geo" ORDER BY "city"; city:s | location_wkt:s | geoshape_wkt:s | region:s -Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |Europe -Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |Europe -Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |Americas -Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |Asia -London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |Europe -Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |Americas -Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |Europe -New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |Americas -Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |Europe -Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|Americas -San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |Americas -Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |Asia -Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |Asia -Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|Asia -Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|Asia +Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |Europe +Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |Europe +Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |Americas +Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |Asia +London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |Europe +Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |Americas +Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |Europe +New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |Americas +Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |Europe +Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|Americas +San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |Americas +Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |Asia +Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |Asia +Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|Asia +Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|Asia ; selectWithAsWKTInWhere SELECT city, ST_ASWKT(location) location_wkt, region FROM "geo" WHERE LOCATE('114', ST_ASWKT(location)) > 0 ORDER BY "city"; city:s | location_wkt:s | region:s -Hong Kong |POINT (114.183925 22.281397)|Asia +Hong Kong |POINT (114.183925 22.281397)|Asia ; selectAllPointsOrderByLonFromAsWKT SELECT city, SUBSTRING(ST_ASWKT(location), 8, LOCATE(' ', ST_ASWKT(location), 8) - 8) lon FROM "geo" ORDER BY lon; city:s | lon:s -London |-0.121672 -Phoenix |-111.973505 -Mountain View |-122.083843 -San Francisco |-122.394228 -New York |-73.990027 -Chicago |-87.637874 -Singapore |103.855535 -Munich |11.537505 -Hong Kong |114.183925 -Seoul |127.060851 -Berlin |13.390889 -Tokyo |139.76402225 -Sydney |151.208629 -Paris |2.351773 -Amsterdam |4.850312 +London |-0.121672 +Phoenix |-111.973505 +Mountain View |-122.083843 +San Francisco |-122.394228 +New York |-73.990027 +Chicago |-87.637874 +Singapore |103.855535 +Munich |11.537505 +Hong Kong |114.183925 +Seoul |127.060851 +Berlin |13.390889 +Tokyo |139.76402225 +Sydney |151.208629 +Paris |2.351773 +Amsterdam |4.850312 ; selectAllPointsGroupByHemisphereFromAsWKT @@ -158,8 +158,8 @@ SELECT region, city, ST_Distance(location, ST_WktToSQL('POINT (-71 42)')) distan region:s | city:s | distance:d Americas |Chicago |1373941.5075370357 -Americas |Mountain View |4335936.907008218 -Americas |New York |285839.6512191343 +Americas |Mountain View |4335936.907008218 +Americas |New York |285839.6512191343 Americas |Phoenix |3692895.0329883597 Americas |San Francisco |4343565.009715615 ; @@ -268,14 +268,14 @@ selectFilterByXOfLocation SELECT city, ST_X(geoshape) x, ST_Y(geoshape) y, ST_Z(geoshape) z, ST_X(location) lx, ST_Y(location) ly FROM geo WHERE lx > 0 ORDER BY ly; city:s | x:d | y:d | z:d | lx:d | ly:d -Sydney |151.208629 |-33.863385 |100.0 |151.208629 |-33.863385 -Singapore |103.855535 |1.295868 |15.0 |103.855535 |1.295868 -Hong Kong |114.183925 |22.281397 |552.0 |114.183925 |22.281397 -Tokyo |139.76402225 |35.669616 |40.0 |139.76402225 |35.669616 -Seoul |127.060851 |37.509132 |38.0 |127.060851 |37.509132 -Munich |11.537505 |48.146321 |519.0 |11.537505 |48.146321 -Paris |2.351773 |48.845538 |35.0 |2.351773 |48.845538 -Amsterdam |4.850312 |52.347557 |2.0 |4.850312 |52.347557 +Sydney |151.208629 |-33.863385 |100.0 |151.208629 |-33.863385 +Singapore |103.855535 |1.295868 |15.0 |103.855535 |1.295868 +Hong Kong |114.183925 |22.281397 |552.0 |114.183925 |22.281397 +Tokyo |139.76402225 |35.669616 |40.0 |139.76402225 |35.669616 +Seoul |127.060851 |37.509132 |38.0 |127.060851 |37.509132 +Munich |11.537505 |48.146321 |519.0 |11.537505 |48.146321 +Paris |2.351773 |48.845538 |35.0 |2.351773 |48.845538 +Amsterdam |4.850312 |52.347557 |2.0 |4.850312 |52.347557 Berlin |13.390889 |52.486701 |34.0 |13.390889 |52.486701 ; @@ -283,10 +283,10 @@ selectFilterByRegionPoint SELECT city, region, ST_X(location) x FROM geo WHERE ST_X(ST_WKTTOSQL(region_point)) < 0 ORDER BY x; city:s | region:s | x:d -San Francisco |Americas |-122.394228 -Mountain View |Americas |-122.083843 -Phoenix |Americas |-111.973505 -Chicago |Americas |-87.637874 +San Francisco |Americas |-122.394228 +Mountain View |Americas |-122.083843 +Phoenix |Americas |-111.973505 +Chicago |Americas |-87.637874 New York |Americas |-73.990027 ; diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command-sys.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command-sys.csv-spec new file mode 100644 index 0000000000000..cf64a70ee74a2 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command-sys.csv-spec @@ -0,0 +1,224 @@ +// To mute tests follow example in file: example.csv-spec + +// +// Sys Commands +// + +sysColumnsWithTableLikeWithEscape +SYS COLUMNS CATALOG 'my_remote_cluster' TABLE LIKE 'test\_emp' ESCAPE '\'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +------------------+---------------+---------------+----------------------+---------------+---------------+---------------+---------------+-----------------+-----------------+-----------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_remote_cluster |null |test_emp |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |4 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |5 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |7 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster |null |test_emp |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |12 |YES |null |null |null |null |NO |NO +; + +// can match multiple clusters +sysColumnsCatalogPatternWithTableLikeWithEscape +SYS COLUMNS CATALOG 'my_*' TABLE LIKE 'test\_emp' ESCAPE '\'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +---------------+---------------+---------------+------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_* |null |test_emp |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |4 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |5 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |7 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |8 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_* |null |test_emp |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |12 |YES |null |null |null |null |NO |NO +; + +sysColumnsWithTableLikeNoEscape +SYS COLUMNS CATALOG 'my_remote_cluster' TABLE LIKE 'test_emp'; + +// since there's no escaping test_emp means test*emp which matches also test_alias_emp +// however as there's no way to filter the matching indices, we can't exclude the field + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +-----------------+---------------+---------------+------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_remote_cluster|null |test_emp |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |extra.info.gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |extra_gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |extra_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |12 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |13 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |14 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |15 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |16 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |null_constant |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |17 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |18 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |wildcard_name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |19 |YES |null |null |null |null |NO |NO +; + +sysColumnsWithCatalogAndLike +SYS COLUMNS CATALOG 'my_remote_cluster' TABLE LIKE 'test\_emp\_copy' ESCAPE '\'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +-----------------+---------------+---------------+------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_remote_cluster|null |test_emp_copy |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra.info.gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra_gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |12 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |13 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |14 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |15 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |16 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |null_constant |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |17 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |18 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |wildcard_name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |19 |YES |null |null |null |null |NO |NO +; + +sysColumnsOnAliasWithTableLike +SYS COLUMNS CATALOG 'my_remote_cluster' TABLE LIKE 'test\_alias' ESCAPE '\'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +-----------------+---------------+---------------+------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_remote_cluster|null |test_alias |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |extra.info.gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |extra_gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |extra_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |12 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |13 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |14 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |15 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |16 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |null_constant |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |17 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |18 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_alias |wildcard_name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |19 |YES |null |null |null |null |NO |NO +; + +sysColumnsAllTables +SYS COLUMNS CATALOG 'my_remote_cluster' TABLE LIKE '%'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | COLUMN_NAME:s | DATA_TYPE:i | TYPE_NAME:s | COLUMN_SIZE:i| BUFFER_LENGTH:i|DECIMAL_DIGITS:i|NUM_PREC_RADIX:i | NULLABLE:i| REMARKS:s | COLUMN_DEF:s |SQL_DATA_TYPE:i|SQL_DATETIME_SUB:i|CHAR_OCTET_LENGTH:i|ORDINAL_POSITION:i|IS_NULLABLE:s|SCOPE_CATALOG:s|SCOPE_SCHEMA:s|SCOPE_TABLE:s|SOURCE_DATA_TYPE:sh|IS_AUTOINCREMENT:s|IS_GENERATEDCOLUMN:s +-----------------+---------------+---------------+------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+----------------+-----------------+----------------+---------------+---------------+---------------+---------------+----------------+----------------+------------------ +my_remote_cluster|null |logs |@timestamp |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |bytes_in |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |2 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |bytes_out |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |client_ip |12 |IP |45 |45 |null |null |1 |null |null |12 |0 |null |4 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |client_port |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |5 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |dest_ip |12 |IP |45 |45 |null |null |1 |null |null |12 |0 |null |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |id |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs |status |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs_nanos |@timestamp |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs_nanos |id |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |2 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |logs_nanos |status |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |4 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |5 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |12 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |birth_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |1 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |emp_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |3 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra.info.gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |6 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra_gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |7 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |extra_no |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |8 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |first_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |9 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |first_name.keyword|12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |10 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |gender |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |11 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |hire_date |93 |DATETIME |34 |8 |null |null |1 |null |null |9 |3 |null |12 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |languages |-6 |BYTE |5 |1 |null |10 |1 |null |null |-6 |0 |null |13 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |last_name |12 |TEXT |2147483647 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |14 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |last_name.keyword |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |15 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |16 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |null_constant |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |17 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |salary |4 |INTEGER |11 |4 |null |10 |1 |null |null |4 |0 |null |18 |YES |null |null |null |null |NO |NO +my_remote_cluster|null |test_emp_copy |wildcard_name |12 |KEYWORD |32766 |2147483647 |null |null |1 |null |null |12 |0 |2147483647 |19 |YES |null |null |null |null |NO |NO +; + +sysTablesSimple +SYS TABLES CATALOG LIKE 'my_remote_cluster'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +my_remote_cluster|null |empty_mapping |TABLE | |null |null |null |null |null +my_remote_cluster|null |logs |TABLE | |null |null |null |null |null +my_remote_cluster|null |logs_nanos |TABLE | |null |null |null |null |null +my_remote_cluster|null |test_emp |TABLE | |null |null |null |null |null +my_remote_cluster|null |test_emp_copy |TABLE | |null |null |null |null |null +; + +sysTablesIndexLikeFilter +SYS TABLES CATALOG LIKE 'my_remote_cluster' LIKE 'empty%'; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +my_remote_cluster|null |empty_mapping |TABLE | |null |null |null |null |null +; + +sysTablesIndexPatternFilter +SYS TABLES CATALOG LIKE 'my_remote_cluster' "empty*"; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +my_remote_cluster|null |empty_mapping |TABLE | |null |null |null |null |null +; + +sysTablesEmptyFilters +SYS TABLES CATALOG LIKE 'my_remote_cluster' "" TYPE ''; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +my_remote_cluster|null |empty_mapping |TABLE | |null |null |null |null |null +my_remote_cluster|null |logs |TABLE | |null |null |null |null |null +my_remote_cluster|null |logs_nanos |TABLE | |null |null |null |null |null +my_remote_cluster|null |test_emp |TABLE | |null |null |null |null |null +my_remote_cluster|null |test_emp_copy |TABLE | |null |null |null |null |null +; + +sysTablesCatalogEnumeration +SYS TABLES CATALOG LIKE '%' LIKE ''; + + TABLE_CAT:s | TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +integTest |null |null |null |null |null |null |null |null |null +my_remote_cluster|null |null |null |null |null |null |null |null |null +; + +sysTablesTypesEnumeration +SYS TABLES CATALOG LIKE '' LIKE ''; + + TABLE_CAT:s| TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +null |null |null |TABLE |null |null |null |null |null |null +null |null |null |VIEW |null |null |null |null |null |null +; + +sysTablesEmptyFilters +SYS TABLES CATALOG LIKE '' "" TYPE ''; + + TABLE_CAT:s| TABLE_SCHEM:s| TABLE_NAME:s | TABLE_TYPE:s | REMARKS:s | TYPE_CAT:s | TYPE_SCHEM:S | TYPE_NAME:s |SELF_REFERENCING_COL_NAME:s|REF_GENERATION:s +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+-------------------------+--------------- +; diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command.csv-spec new file mode 100644 index 0000000000000..a7caaf5b03c06 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/src/main/resources/multi-cluster-with-security/multi-cluster-command.csv-spec @@ -0,0 +1,334 @@ +// To mute tests follow example in file: example.csv-spec + +// +// Commands +// + +// Note: remote index discovery (for CCS) won't list aliases. + +showCatalogs +SHOW CATALOGS; + + name | type +------------------+--------------- +integTest |local +my_remote_cluster |remote +; + +showTables +SHOW TABLES CATALOG 'my_remote_cluster'; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|empty_mapping |TABLE |INDEX +my_remote_cluster|logs |TABLE |INDEX +my_remote_cluster|logs_nanos |TABLE |INDEX +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX +; + +showTablesWithLike +SHOW TABLES CATALOG LIKE 'my_remote_%'; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|empty_mapping |TABLE |INDEX +my_remote_cluster|logs |TABLE |INDEX +my_remote_cluster|logs_nanos |TABLE |INDEX +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX +; + +showTablesWithFrozen +SHOW TABLES CATALOG 'my_remote_cluster' INCLUDE FROZEN; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|empty_mapping |TABLE |INDEX +my_remote_cluster|frozen_emp |TABLE |INDEX +my_remote_cluster|logs |TABLE |INDEX +my_remote_cluster|logs_nanos |TABLE |INDEX +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX +; + +showTablesSimpleLike +SHOW TABLES CATALOG 'my_remote_cluster' LIKE 'test_emp'; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|test_emp |TABLE |INDEX +; + +showTablesCatalogPatternMultiLike +SHOW TABLES CATALOG 'my_*' LIKE 'test_emp%'; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX + +; + +showTablesList +SHOW TABLES CATALOG 'my_*' "test_emp,test_emp_copy"; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX + +; + +showTablesIdentifier +SHOW TABLES CATALOG 'my_remote_cluster' "test_emp"; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|test_emp |TABLE |INDEX +; + +showTablesIdentifierPattern +SHOW TABLES CATALOG 'my*' "test_e*,-test_emp"; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|test_emp_copy |TABLE |INDEX + +; + +// Aliases not supported with remote clusters +showTablesIdentifierPatternOnAliases-Ignore +SHOW TABLES CATALOG 'my*' "test*,-test_emp*"; + + name:s | type:s | kind:s +test_alias |VIEW |ALIAS +test_alias_emp |VIEW |ALIAS +; + +showTablesAllCatalogs +SHOW TABLES CATALOG '*'; + + catalog | name | type | kind +-----------------+---------------+---------------+--------------- +my_remote_cluster|empty_mapping |TABLE |INDEX +my_remote_cluster|logs |TABLE |INDEX +my_remote_cluster|logs_nanos |TABLE |INDEX +my_remote_cluster|test_emp |TABLE |INDEX +my_remote_cluster|test_emp_copy |TABLE |INDEX +; + +// DESCRIBE + +describeSimpleLike +DESCRIBE CATALOG 'my_*' LIKE 'test_emp'; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword +; + +describeMultiLike +DESCRIBE CATALOG 'my_remote_cluster' LIKE 'test_emp%'; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword +; + +describeSimpleIdentifier +DESCRIBE CATALOG 'my_remote_cluster' "test_emp"; + + column | type | mapping +----------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer +; + +// NB: need to pursue how the resolution is done +// should aliases be included or excluded? +describeIncludeExcludeIdentifier-Ignore +DESCRIBE CATALOG 'my_*' "test_*,-test_alias*"; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +salary |INTEGER |integer +; + +describeNoCols +DESCRIBE CATALOG 'my_remote_cluster' "empty_mapping"; + + column:s | type:s | mapping:s +----------------------+---------------+--------------- +; + + +showColumnsInNoCols +SHOW COLUMNS CATALOG 'my_remote_cluster' IN "empty_mapping"; + + column:s | type:s | mapping:s +----------------------+---------------+--------------- +; + +showColumnsSimpleIdentifier +SHOW COLUMNS CATALOG 'my_remote_cluster' IN "test_emp"; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer +; + +showColumnsIndexPattern +SHOW COLUMNS CATALOG 'my_remote_cluster' IN "test_*"; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword +; + +showColumnsCatalogAndIndexPattern +SHOW COLUMNS CATALOG 'my_*' IN "test_*"; + + column | type | mapping +--------------------+---------------+--------------- +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword +; + diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/ogc/ogc.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/ogc/ogc.csv-spec index bd2c10a525c61..f31dd52a6ea86 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/ogc/ogc.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/ogc/ogc.csv-spec @@ -7,8 +7,8 @@ showTables SHOW TABLES "ogc"; - name:s | type:s | kind:s -ogc |TABLE |INDEX + catalog:s | name:s | type:s| kind:s +integTest |ogc |TABLE |INDEX ; // DESCRIBE diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/setup_mock_show_tables.sql b/x-pack/plugin/sql/qa/server/src/main/resources/setup_mock_show_tables.sql index 53286eadc5261..65aee9e6c92a2 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/setup_mock_show_tables.sql +++ b/x-pack/plugin/sql/qa/server/src/main/resources/setup_mock_show_tables.sql @@ -1,4 +1,5 @@ CREATE TABLE mock ( + "catalog" VARCHAR, "name" VARCHAR, "type" VARCHAR, "kind" VARCHAR diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/slow/frozen.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/slow/frozen.csv-spec index 650c76089d272..2b5da3da451f5 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/slow/frozen.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/slow/frozen.csv-spec @@ -7,15 +7,15 @@ showTables SHOW TABLES INCLUDE FROZEN; - name | type | kind -empty_mapping |TABLE |INDEX -frozen_emp |TABLE |FROZEN INDEX -logs |TABLE |INDEX -logs_nanos |TABLE |INDEX -test_alias |VIEW |ALIAS -test_alias_emp |VIEW |ALIAS -test_emp |TABLE |INDEX -test_emp_copy |TABLE |INDEX + catalog | name | type | kind +integTest |empty_mapping |TABLE |INDEX +integTest |frozen_emp |TABLE |FROZEN INDEX +integTest |logs |TABLE |INDEX +integTest |logs_nanos |TABLE |INDEX +integTest |test_alias |VIEW |ALIAS +integTest |test_alias_emp |VIEW |ALIAS +integTest |test_emp |TABLE |INDEX +integTest |test_emp_copy |TABLE |INDEX ; columnFromFrozen diff --git a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 index baf17bb270503..0e9dc2a5aae16 100644 --- a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 +++ b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 @@ -50,11 +50,18 @@ statement )* ')')? statement #debug - | SHOW TABLES (INCLUDE FROZEN)? (tableLike=likePattern | tableIdent=tableIdentifier)? #showTables - | SHOW COLUMNS (INCLUDE FROZEN)? (FROM | IN) (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns - | (DESCRIBE | DESC) (INCLUDE FROZEN)? (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns + | SHOW TABLES (CATALOG (clusterLike=likePattern | cluster=string))? + (INCLUDE FROZEN)? + (tableLike=likePattern | tableIdent=tableIdentifier)? #showTables + | SHOW COLUMNS (CATALOG cluster=string)? + (INCLUDE FROZEN)? + (FROM | IN) (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns + | (DESCRIBE | DESC) (CATALOG cluster=string)? + (INCLUDE FROZEN)? + (tableLike=likePattern | tableIdent=tableIdentifier) #showColumns | SHOW FUNCTIONS (likePattern)? #showFunctions | SHOW SCHEMAS #showSchemas + | SHOW CATALOGS #showCatalogs | SYS TABLES (CATALOG clusterLike=likePattern)? (tableLike=likePattern | tableIdent=tableIdentifier)? (TYPE string (',' string)* )? #sysTables @@ -63,7 +70,7 @@ statement (columnPattern=likePattern)? #sysColumns | SYS TYPES ((PLUS | MINUS)? type=number)? #sysTypes ; - + query : (WITH namedQuery (',' namedQuery)*)? queryNoWith ; @@ -76,10 +83,10 @@ queryNoWith ; limitClause - : LIMIT limit=(INTEGER_VALUE | ALL) - | LIMIT_ESC limit=(INTEGER_VALUE | ALL) ESC_END + : LIMIT limit=(INTEGER_VALUE | ALL) + | LIMIT_ESC limit=(INTEGER_VALUE | ALL) ESC_END ; - + queryTerm : querySpecification #queryPrimaryDefault | '(' queryNoWith ')' #subquery @@ -127,7 +134,7 @@ setQuantifier | ALL ; -selectItems +selectItems : selectItem (',' selectItem)* ; @@ -167,13 +174,13 @@ pivotClause ; pivotArgs - : namedValueExpression (',' namedValueExpression)* + : namedValueExpression (',' namedValueExpression)* ; - + namedValueExpression : valueExpression (AS? identifier)? ; - + expression : booleanExpression ; @@ -214,11 +221,11 @@ predicate likePattern : LIKE pattern ; - + pattern : value=string patternEscape? ; - + patternEscape : ESCAPE escape=string | ESCAPE_ESC escape=string ESC_END @@ -271,7 +278,7 @@ extractExpression : extractTemplate | FUNCTION_ESC extractTemplate ESC_END ; - + extractTemplate : EXTRACT '(' field=identifier FROM valueExpression ')' ; @@ -280,16 +287,16 @@ functionExpression : functionTemplate | FUNCTION_ESC functionTemplate ESC_END ; - + functionTemplate : functionName '(' (setQuantifier? expression (',' expression)*)? ')' ; functionName - : LEFT - | RIGHT + : LEFT + | RIGHT | identifier ; - + constant : NULL #nullLiteral | interval #intervalLiteral @@ -312,9 +319,9 @@ booleanValue ; interval - : INTERVAL sign=(PLUS | MINUS)? (valueNumeric=number | valuePattern=string) leading=intervalField (TO trailing=intervalField)? + : INTERVAL sign=(PLUS | MINUS)? (valueNumeric=number | valuePattern=string) leading=intervalField (TO trailing=intervalField)? ; - + intervalField : YEAR | YEARS | MONTH | MONTHS | DAY | DAYS | HOUR | HOURS | MINUTE | MINUTES | SECOND | SECONDS ; @@ -365,19 +372,19 @@ whenClause // http://developer.mimer.se/validator/sql-reserved-words.tml // https://developer.mimer.com/wp-content/uploads/standard-sql-reserved-words-summary.pdf nonReserved - : ANALYZE | ANALYZED + : ANALYZE | ANALYZED | CATALOGS | COLUMNS | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP - | DAY | DEBUG - | EXECUTABLE | EXPLAIN + | DAY | DEBUG + | EXECUTABLE | EXPLAIN | FIRST | FORMAT | FULL | FUNCTIONS | GRAPHVIZ | HOUR | INTERVAL - | LAST | LIMIT + | LAST | LIMIT | MAPPED | MINUTE | MONTH - | OPTIMIZED - | PARSED | PHYSICAL | PIVOT | PLAN - | QUERY + | OPTIMIZED + | PARSED | PHYSICAL | PIVOT | PLAN + | QUERY | RLIKE | SCHEMAS | SECOND | SHOW | SYS | TABLES | TEXT | TOP | TYPE | TYPES diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java index 77ecaab060e4e..2d3fe5c35110c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java @@ -302,14 +302,17 @@ protected boolean skipResolved() { private class ResolveTable extends AnalyzerRule { @Override protected LogicalPlan rule(UnresolvedRelation plan) { - TableIdentifier table = plan.table(); if (indexResolution.isValid() == false) { return plan.unresolvedMessage().equals(indexResolution.toString()) ? plan : new UnresolvedRelation(plan.source(), plan.table(), plan.alias(), plan.frozen(), indexResolution.toString()); } - assert indexResolution.matches(table.index()); + TableIdentifier table = plan.table(); + if (indexResolution.matches(table.index()) == false) { + new UnresolvedRelation(plan.source(), plan.table(), plan.alias(), plan.frozen(), + "invalid [" + table + "] resolution to [" + indexResolution + "]"); + } LogicalPlan logicalPlan = new EsRelation(plan.source(), indexResolution.get(), plan.frozen()); - SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, table.index()); + SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, table.toString()); if (plan.alias() != null) { sa = new SubQueryAlias(plan.source(), sa, plan.alias()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java index e4e81cdcfb381..44c8792691f0a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java @@ -17,6 +17,7 @@ import org.elasticsearch.xpack.ql.util.StringUtils; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.DebugContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ExplainContext; +import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ShowCatalogsContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ShowColumnsContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ShowFunctionsContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ShowSchemasContext; @@ -28,6 +29,7 @@ import org.elasticsearch.xpack.sql.plan.logical.command.Command; import org.elasticsearch.xpack.sql.plan.logical.command.Debug; import org.elasticsearch.xpack.sql.plan.logical.command.Explain; +import org.elasticsearch.xpack.sql.plan.logical.command.ShowCatalogs; import org.elasticsearch.xpack.sql.plan.logical.command.ShowColumns; import org.elasticsearch.xpack.sql.plan.logical.command.ShowFunctions; import org.elasticsearch.xpack.sql.plan.logical.command.ShowSchemas; @@ -131,7 +133,8 @@ public Object visitShowFunctions(ShowFunctionsContext ctx) { public Object visitShowTables(ShowTablesContext ctx) { TableIdentifier ti = visitTableIdentifier(ctx.tableIdent); String index = ti != null ? ti.qualifiedIndex() : null; - return new ShowTables(source(ctx), index, visitLikePattern(ctx.likePattern()), ctx.FROZEN() != null); + return new ShowTables(source(ctx), visitLikePattern(ctx.clusterLike), visitString(ctx.cluster), index, + visitLikePattern(ctx.tableLike), ctx.FROZEN() != null); } @Override @@ -143,7 +146,12 @@ public Object visitShowSchemas(ShowSchemasContext ctx) { public Object visitShowColumns(ShowColumnsContext ctx) { TableIdentifier ti = visitTableIdentifier(ctx.tableIdent); String index = ti != null ? ti.qualifiedIndex() : null; - return new ShowColumns(source(ctx), index, visitLikePattern(ctx.likePattern()), ctx.FROZEN() != null); + return new ShowColumns(source(ctx), string(ctx.cluster), index, visitLikePattern(ctx.tableLike), ctx.FROZEN() != null); + } + + @Override + public Object visitShowCatalogs(ShowCatalogsContext ctx) { + return new ShowCatalogs(source(ctx)); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseListener.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseListener.java index 2817c9c348ee6..a0e87bd707c70 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseListener.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseListener.java @@ -119,6 +119,18 @@ class SqlBaseBaseListener implements SqlBaseListener { *

The default implementation does nothing.

*/ @Override public void exitShowSchemas(SqlBaseParser.ShowSchemasContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx) { } /** * {@inheritDoc} * diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseVisitor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseVisitor.java index ae605407a1c15..720ce36cfd173 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseVisitor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseBaseVisitor.java @@ -74,6 +74,13 @@ class SqlBaseBaseVisitor extends AbstractParseTreeVisitor implements SqlBa * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitShowSchemas(SqlBaseParser.ShowSchemasContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

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

+ */ + @Override public T visitShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseListener.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseListener.java index 5280db14199f2..d943be197a2c2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseListener.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseListener.java @@ -111,6 +111,18 @@ interface SqlBaseListener extends ParseTreeListener { * @param ctx the parse tree */ void exitShowSchemas(SqlBaseParser.ShowSchemasContext ctx); + /** + * Enter a parse tree produced by the {@code showCatalogs} + * labeled alternative in {@link SqlBaseParser#statement}. + * @param ctx the parse tree + */ + void enterShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx); + /** + * Exit a parse tree produced by the {@code showCatalogs} + * labeled alternative in {@link SqlBaseParser#statement}. + * @param ctx the parse tree + */ + void exitShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx); /** * Enter a parse tree produced by the {@code sysTables} * labeled alternative in {@link SqlBaseParser#statement}. diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java index b0d494e539066..04f0b7a987d76 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java @@ -458,6 +458,24 @@ public T accept(ParseTreeVisitor visitor) { else return visitor.visitChildren(this); } } + public static class ShowCatalogsContext extends StatementContext { + public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } + public TerminalNode CATALOGS() { return getToken(SqlBaseParser.CATALOGS, 0); } + public ShowCatalogsContext(StatementContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterShowCatalogs(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitShowCatalogs(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitShowCatalogs(this); + else return visitor.visitChildren(this); + } + } public static class StatementDefaultContext extends StatementContext { public QueryContext query() { return getRuleContext(QueryContext.class,0); @@ -537,18 +555,27 @@ public T accept(ParseTreeVisitor visitor) { } } public static class ShowTablesContext extends StatementContext { + public LikePatternContext clusterLike; + public StringContext cluster; public LikePatternContext tableLike; public TableIdentifierContext tableIdent; public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } public TerminalNode TABLES() { return getToken(SqlBaseParser.TABLES, 0); } + public TerminalNode CATALOG() { return getToken(SqlBaseParser.CATALOG, 0); } public TerminalNode INCLUDE() { return getToken(SqlBaseParser.INCLUDE, 0); } public TerminalNode FROZEN() { return getToken(SqlBaseParser.FROZEN, 0); } - public LikePatternContext likePattern() { - return getRuleContext(LikePatternContext.class,0); + public List likePattern() { + return getRuleContexts(LikePatternContext.class); + } + public LikePatternContext likePattern(int i) { + return getRuleContext(LikePatternContext.class,i); } public TableIdentifierContext tableIdentifier() { return getRuleContext(TableIdentifierContext.class,0); } + public StringContext string() { + return getRuleContext(StringContext.class,0); + } public ShowTablesContext(StatementContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { @@ -583,12 +610,14 @@ public T accept(ParseTreeVisitor visitor) { } } public static class ShowColumnsContext extends StatementContext { + public StringContext cluster; public LikePatternContext tableLike; public TableIdentifierContext tableIdent; public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } public TerminalNode COLUMNS() { return getToken(SqlBaseParser.COLUMNS, 0); } public TerminalNode FROM() { return getToken(SqlBaseParser.FROM, 0); } public TerminalNode IN() { return getToken(SqlBaseParser.IN, 0); } + public TerminalNode CATALOG() { return getToken(SqlBaseParser.CATALOG, 0); } public TerminalNode INCLUDE() { return getToken(SqlBaseParser.INCLUDE, 0); } public TerminalNode FROZEN() { return getToken(SqlBaseParser.FROZEN, 0); } public LikePatternContext likePattern() { @@ -597,6 +626,9 @@ public LikePatternContext likePattern() { public TableIdentifierContext tableIdentifier() { return getRuleContext(TableIdentifierContext.class,0); } + public StringContext string() { + return getRuleContext(StringContext.class,0); + } public TerminalNode DESCRIBE() { return getToken(SqlBaseParser.DESCRIBE, 0); } public TerminalNode DESC() { return getToken(SqlBaseParser.DESC, 0); } public ShowColumnsContext(StatementContext ctx) { copyFrom(ctx); } @@ -620,9 +652,9 @@ public final StatementContext statement() throws RecognitionException { enterRule(_localctx, 4, RULE_statement); int _la; try { - setState(239); + setState(256); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) { case 1: _localctx = new StatementDefaultContext(_localctx); enterOuterAlt(_localctx, 1); @@ -791,24 +823,53 @@ public final StatementContext statement() throws RecognitionException { match(SHOW); setState(160); match(TABLES); - setState(163); + setState(166); _errHandler.sync(this); _la = _input.LA(1); - if (_la==INCLUDE) { + if (_la==CATALOG) { { setState(161); + match(CATALOG); + setState(164); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LIKE: + { + setState(162); + ((ShowTablesContext)_localctx).clusterLike = likePattern(); + } + break; + case PARAM: + case STRING: + { + setState(163); + ((ShowTablesContext)_localctx).cluster = string(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + + setState(170); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==INCLUDE) { + { + setState(168); match(INCLUDE); - setState(162); + setState(169); match(FROZEN); } } - setState(167); + setState(174); _errHandler.sync(this); switch (_input.LA(1)) { case LIKE: { - setState(165); + setState(172); ((ShowTablesContext)_localctx).tableLike = likePattern(); } break; @@ -859,7 +920,7 @@ public final StatementContext statement() throws RecognitionException { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: { - setState(166); + setState(173); ((ShowTablesContext)_localctx).tableIdent = tableIdentifier(); } break; @@ -874,23 +935,35 @@ public final StatementContext statement() throws RecognitionException { _localctx = new ShowColumnsContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(169); + setState(176); match(SHOW); - setState(170); + setState(177); match(COLUMNS); - setState(173); + setState(180); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==CATALOG) { + { + setState(178); + match(CATALOG); + setState(179); + ((ShowColumnsContext)_localctx).cluster = string(); + } + } + + setState(184); _errHandler.sync(this); _la = _input.LA(1); if (_la==INCLUDE) { { - setState(171); + setState(182); match(INCLUDE); - setState(172); + setState(183); match(FROZEN); } } - setState(175); + setState(186); _la = _input.LA(1); if ( !(_la==FROM || _la==IN) ) { _errHandler.recoverInline(this); @@ -900,12 +973,12 @@ public final StatementContext statement() throws RecognitionException { _errHandler.reportMatch(this); consume(); } - setState(178); + setState(189); _errHandler.sync(this); switch (_input.LA(1)) { case LIKE: { - setState(176); + setState(187); ((ShowColumnsContext)_localctx).tableLike = likePattern(); } break; @@ -956,7 +1029,7 @@ public final StatementContext statement() throws RecognitionException { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: { - setState(177); + setState(188); ((ShowColumnsContext)_localctx).tableIdent = tableIdentifier(); } break; @@ -969,7 +1042,7 @@ public final StatementContext statement() throws RecognitionException { _localctx = new ShowColumnsContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(180); + setState(191); _la = _input.LA(1); if ( !(_la==DESC || _la==DESCRIBE) ) { _errHandler.recoverInline(this); @@ -979,24 +1052,36 @@ public final StatementContext statement() throws RecognitionException { _errHandler.reportMatch(this); consume(); } - setState(183); + setState(194); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==CATALOG) { + { + setState(192); + match(CATALOG); + setState(193); + ((ShowColumnsContext)_localctx).cluster = string(); + } + } + + setState(198); _errHandler.sync(this); _la = _input.LA(1); if (_la==INCLUDE) { { - setState(181); + setState(196); match(INCLUDE); - setState(182); + setState(197); match(FROZEN); } } - setState(187); + setState(202); _errHandler.sync(this); switch (_input.LA(1)) { case LIKE: { - setState(185); + setState(200); ((ShowColumnsContext)_localctx).tableLike = likePattern(); } break; @@ -1047,7 +1132,7 @@ public final StatementContext statement() throws RecognitionException { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: { - setState(186); + setState(201); ((ShowColumnsContext)_localctx).tableIdent = tableIdentifier(); } break; @@ -1060,16 +1145,16 @@ public final StatementContext statement() throws RecognitionException { _localctx = new ShowFunctionsContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(189); + setState(204); match(SHOW); - setState(190); + setState(205); match(FUNCTIONS); - setState(192); + setState(207); _errHandler.sync(this); _la = _input.LA(1); if (_la==LIKE) { { - setState(191); + setState(206); likePattern(); } } @@ -1080,70 +1165,80 @@ public final StatementContext statement() throws RecognitionException { _localctx = new ShowSchemasContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(194); + setState(209); match(SHOW); - setState(195); + setState(210); match(SCHEMAS); } break; case 9: - _localctx = new SysTablesContext(_localctx); + _localctx = new ShowCatalogsContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(196); + setState(211); + match(SHOW); + setState(212); + match(CATALOGS); + } + break; + case 10: + _localctx = new SysTablesContext(_localctx); + enterOuterAlt(_localctx, 10); + { + setState(213); match(SYS); - setState(197); + setState(214); match(TABLES); - setState(200); + setState(217); _errHandler.sync(this); _la = _input.LA(1); if (_la==CATALOG) { { - setState(198); + setState(215); match(CATALOG); - setState(199); + setState(216); ((SysTablesContext)_localctx).clusterLike = likePattern(); } } - setState(204); + setState(221); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: { - setState(202); + setState(219); ((SysTablesContext)_localctx).tableLike = likePattern(); } break; case 2: { - setState(203); + setState(220); ((SysTablesContext)_localctx).tableIdent = tableIdentifier(); } break; } - setState(215); + setState(232); _errHandler.sync(this); _la = _input.LA(1); if (_la==TYPE) { { - setState(206); + setState(223); match(TYPE); - setState(207); + setState(224); string(); - setState(212); + setState(229); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(208); + setState(225); match(T__2); - setState(209); + setState(226); string(); } } - setState(214); + setState(231); _errHandler.sync(this); _la = _input.LA(1); } @@ -1152,34 +1247,34 @@ public final StatementContext statement() throws RecognitionException { } break; - case 10: + case 11: _localctx = new SysColumnsContext(_localctx); - enterOuterAlt(_localctx, 10); + enterOuterAlt(_localctx, 11); { - setState(217); + setState(234); match(SYS); - setState(218); + setState(235); match(COLUMNS); - setState(221); + setState(238); _errHandler.sync(this); _la = _input.LA(1); if (_la==CATALOG) { { - setState(219); + setState(236); match(CATALOG); - setState(220); + setState(237); ((SysColumnsContext)_localctx).cluster = string(); } } - setState(226); + setState(243); _errHandler.sync(this); switch (_input.LA(1)) { case TABLE: { - setState(223); + setState(240); match(TABLE); - setState(224); + setState(241); ((SysColumnsContext)_localctx).tableLike = likePattern(); } break; @@ -1230,7 +1325,7 @@ public final StatementContext statement() throws RecognitionException { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: { - setState(225); + setState(242); ((SysColumnsContext)_localctx).tableIdent = tableIdentifier(); } break; @@ -1240,37 +1335,37 @@ public final StatementContext statement() throws RecognitionException { default: break; } - setState(229); + setState(246); _errHandler.sync(this); _la = _input.LA(1); if (_la==LIKE) { { - setState(228); + setState(245); ((SysColumnsContext)_localctx).columnPattern = likePattern(); } } } break; - case 11: + case 12: _localctx = new SysTypesContext(_localctx); - enterOuterAlt(_localctx, 11); + enterOuterAlt(_localctx, 12); { - setState(231); + setState(248); match(SYS); - setState(232); + setState(249); match(TYPES); - setState(237); + setState(254); _errHandler.sync(this); _la = _input.LA(1); if (((((_la - 119)) & ~0x3f) == 0 && ((1L << (_la - 119)) & ((1L << (PLUS - 119)) | (1L << (MINUS - 119)) | (1L << (INTEGER_VALUE - 119)) | (1L << (DECIMAL_VALUE - 119)))) != 0)) { { - setState(234); + setState(251); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(233); + setState(250); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -1283,7 +1378,7 @@ public final StatementContext statement() throws RecognitionException { } } - setState(236); + setState(253); ((SysTypesContext)_localctx).type = number(); } } @@ -1340,35 +1435,35 @@ public final QueryContext query() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(250); + setState(267); _errHandler.sync(this); _la = _input.LA(1); if (_la==WITH) { { - setState(241); + setState(258); match(WITH); - setState(242); + setState(259); namedQuery(); - setState(247); + setState(264); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(243); + setState(260); match(T__2); - setState(244); + setState(261); namedQuery(); } } - setState(249); + setState(266); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(252); + setState(269); queryNoWith(); } } @@ -1424,44 +1519,44 @@ public final QueryNoWithContext queryNoWith() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(254); + setState(271); queryTerm(); - setState(265); + setState(282); _errHandler.sync(this); _la = _input.LA(1); if (_la==ORDER) { { - setState(255); + setState(272); match(ORDER); - setState(256); + setState(273); match(BY); - setState(257); + setState(274); orderBy(); - setState(262); + setState(279); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(258); + setState(275); match(T__2); - setState(259); + setState(276); orderBy(); } } - setState(264); + setState(281); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(268); + setState(285); _errHandler.sync(this); _la = _input.LA(1); if (_la==LIMIT || _la==LIMIT_ESC) { { - setState(267); + setState(284); limitClause(); } } @@ -1510,15 +1605,15 @@ public final LimitClauseContext limitClause() throws RecognitionException { enterRule(_localctx, 10, RULE_limitClause); int _la; try { - setState(275); + setState(292); _errHandler.sync(this); switch (_input.LA(1)) { case LIMIT: enterOuterAlt(_localctx, 1); { - setState(270); + setState(287); match(LIMIT); - setState(271); + setState(288); ((LimitClauseContext)_localctx).limit = _input.LT(1); _la = _input.LA(1); if ( !(_la==ALL || _la==INTEGER_VALUE) ) { @@ -1534,9 +1629,9 @@ public final LimitClauseContext limitClause() throws RecognitionException { case LIMIT_ESC: enterOuterAlt(_localctx, 2); { - setState(272); + setState(289); match(LIMIT_ESC); - setState(273); + setState(290); ((LimitClauseContext)_localctx).limit = _input.LT(1); _la = _input.LA(1); if ( !(_la==ALL || _la==INTEGER_VALUE) ) { @@ -1547,7 +1642,7 @@ public final LimitClauseContext limitClause() throws RecognitionException { _errHandler.reportMatch(this); consume(); } - setState(274); + setState(291); match(ESC_END); } break; @@ -1620,14 +1715,14 @@ public final QueryTermContext queryTerm() throws RecognitionException { QueryTermContext _localctx = new QueryTermContext(_ctx, getState()); enterRule(_localctx, 12, RULE_queryTerm); try { - setState(282); + setState(299); _errHandler.sync(this); switch (_input.LA(1)) { case SELECT: _localctx = new QueryPrimaryDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(277); + setState(294); querySpecification(); } break; @@ -1635,11 +1730,11 @@ public final QueryTermContext queryTerm() throws RecognitionException { _localctx = new SubqueryContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(278); + setState(295); match(T__0); - setState(279); + setState(296); queryNoWith(); - setState(280); + setState(297); match(T__1); } break; @@ -1695,14 +1790,14 @@ public final OrderByContext orderBy() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(284); + setState(301); expression(); - setState(286); + setState(303); _errHandler.sync(this); _la = _input.LA(1); if (_la==ASC || _la==DESC) { { - setState(285); + setState(302); ((OrderByContext)_localctx).ordering = _input.LT(1); _la = _input.LA(1); if ( !(_la==ASC || _la==DESC) ) { @@ -1716,14 +1811,14 @@ public final OrderByContext orderBy() throws RecognitionException { } } - setState(290); + setState(307); _errHandler.sync(this); _la = _input.LA(1); if (_la==NULLS) { { - setState(288); + setState(305); match(NULLS); - setState(289); + setState(306); ((OrderByContext)_localctx).nullOrdering = _input.LT(1); _la = _input.LA(1); if ( !(_la==FIRST || _la==LAST) ) { @@ -1805,74 +1900,74 @@ public final QuerySpecificationContext querySpecification() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(292); + setState(309); match(SELECT); - setState(294); + setState(311); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) { case 1: { - setState(293); + setState(310); topClause(); } break; } - setState(297); + setState(314); _errHandler.sync(this); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(296); + setState(313); setQuantifier(); } } - setState(299); + setState(316); selectItems(); - setState(301); + setState(318); _errHandler.sync(this); _la = _input.LA(1); if (_la==FROM) { { - setState(300); + setState(317); fromClause(); } } - setState(305); + setState(322); _errHandler.sync(this); _la = _input.LA(1); if (_la==WHERE) { { - setState(303); + setState(320); match(WHERE); - setState(304); + setState(321); ((QuerySpecificationContext)_localctx).where = booleanExpression(0); } } - setState(310); + setState(327); _errHandler.sync(this); _la = _input.LA(1); if (_la==GROUP) { { - setState(307); + setState(324); match(GROUP); - setState(308); + setState(325); match(BY); - setState(309); + setState(326); groupBy(); } } - setState(314); + setState(331); _errHandler.sync(this); _la = _input.LA(1); if (_la==HAVING) { { - setState(312); + setState(329); match(HAVING); - setState(313); + setState(330); ((QuerySpecificationContext)_localctx).having = booleanExpression(0); } } @@ -1927,32 +2022,32 @@ public final FromClauseContext fromClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(316); + setState(333); match(FROM); - setState(317); + setState(334); relation(); - setState(322); + setState(339); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(318); + setState(335); match(T__2); - setState(319); + setState(336); relation(); } } - setState(324); + setState(341); _errHandler.sync(this); _la = _input.LA(1); } - setState(326); + setState(343); _errHandler.sync(this); _la = _input.LA(1); if (_la==PIVOT) { { - setState(325); + setState(342); pivotClause(); } } @@ -2006,31 +2101,31 @@ public final GroupByContext groupBy() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(329); + setState(346); _errHandler.sync(this); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(328); + setState(345); setQuantifier(); } } - setState(331); + setState(348); groupingElement(); - setState(336); + setState(353); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(332); + setState(349); match(T__2); - setState(333); + setState(350); groupingElement(); } } - setState(338); + setState(355); _errHandler.sync(this); _la = _input.LA(1); } @@ -2085,7 +2180,7 @@ public final GroupingElementContext groupingElement() throws RecognitionExceptio _localctx = new SingleGroupingSetContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(339); + setState(356); groupingExpressions(); } } @@ -2131,48 +2226,48 @@ public final GroupingExpressionsContext groupingExpressions() throws Recognition enterRule(_localctx, 24, RULE_groupingExpressions); int _la; try { - setState(354); + setState(371); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,44,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,48,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(341); + setState(358); match(T__0); - setState(350); + setState(367); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CASE) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CONVERT) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LEFT) | (1L << LIMIT) | (1L << MAPPED) | (1L << MATCH) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 66)) & ~0x3f) == 0 && ((1L << (_la - 66)) & ((1L << (NOT - 66)) | (1L << (NULL - 66)) | (1L << (OPTIMIZED - 66)) | (1L << (PARSED - 66)) | (1L << (PHYSICAL - 66)) | (1L << (PIVOT - 66)) | (1L << (PLAN - 66)) | (1L << (RIGHT - 66)) | (1L << (RLIKE - 66)) | (1L << (QUERY - 66)) | (1L << (SCHEMAS - 66)) | (1L << (SECOND - 66)) | (1L << (SHOW - 66)) | (1L << (SYS - 66)) | (1L << (TABLES - 66)) | (1L << (TEXT - 66)) | (1L << (TRUE - 66)) | (1L << (TOP - 66)) | (1L << (TYPE - 66)) | (1L << (TYPES - 66)) | (1L << (VERIFY - 66)) | (1L << (YEAR - 66)) | (1L << (FUNCTION_ESC - 66)) | (1L << (DATE_ESC - 66)) | (1L << (TIME_ESC - 66)) | (1L << (TIMESTAMP_ESC - 66)) | (1L << (GUID_ESC - 66)) | (1L << (PLUS - 66)) | (1L << (MINUS - 66)) | (1L << (ASTERISK - 66)) | (1L << (PARAM - 66)) | (1L << (STRING - 66)) | (1L << (INTEGER_VALUE - 66)) | (1L << (DECIMAL_VALUE - 66)))) != 0) || ((((_la - 130)) & ~0x3f) == 0 && ((1L << (_la - 130)) & ((1L << (IDENTIFIER - 130)) | (1L << (DIGIT_IDENTIFIER - 130)) | (1L << (QUOTED_IDENTIFIER - 130)) | (1L << (BACKQUOTED_IDENTIFIER - 130)))) != 0)) { { - setState(342); + setState(359); expression(); - setState(347); + setState(364); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(343); + setState(360); match(T__2); - setState(344); + setState(361); expression(); } } - setState(349); + setState(366); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(352); + setState(369); match(T__1); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(353); + setState(370); expression(); } break; @@ -2223,15 +2318,15 @@ public final NamedQueryContext namedQuery() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(356); + setState(373); ((NamedQueryContext)_localctx).name = identifier(); - setState(357); + setState(374); match(AS); - setState(358); + setState(375); match(T__0); - setState(359); + setState(376); queryNoWith(); - setState(360); + setState(377); match(T__1); } } @@ -2275,9 +2370,9 @@ public final TopClauseContext topClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(362); + setState(379); match(TOP); - setState(363); + setState(380); ((TopClauseContext)_localctx).top = match(INTEGER_VALUE); } } @@ -2321,7 +2416,7 @@ public final SetQuantifierContext setQuantifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(365); + setState(382); _la = _input.LA(1); if ( !(_la==ALL || _la==DISTINCT) ) { _errHandler.recoverInline(this); @@ -2377,21 +2472,21 @@ public final SelectItemsContext selectItems() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(367); + setState(384); selectItem(); - setState(372); + setState(389); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(368); + setState(385); match(T__2); - setState(369); + setState(386); selectItem(); } } - setState(374); + setState(391); _errHandler.sync(this); _la = _input.LA(1); } @@ -2451,24 +2546,24 @@ public final SelectItemContext selectItem() throws RecognitionException { _localctx = new SelectExpressionContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(375); + setState(392); expression(); - setState(380); + setState(397); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { - setState(377); + setState(394); _errHandler.sync(this); _la = _input.LA(1); if (_la==AS) { { - setState(376); + setState(393); match(AS); } } - setState(379); + setState(396); identifier(); } break; @@ -2522,19 +2617,19 @@ public final RelationContext relation() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(382); + setState(399); relationPrimary(); - setState(386); + setState(403); _errHandler.sync(this); _la = _input.LA(1); while (((((_la - 42)) & ~0x3f) == 0 && ((1L << (_la - 42)) & ((1L << (FULL - 42)) | (1L << (INNER - 42)) | (1L << (JOIN - 42)) | (1L << (LEFT - 42)) | (1L << (NATURAL - 42)) | (1L << (RIGHT - 42)))) != 0)) { { { - setState(383); + setState(400); joinRelation(); } } - setState(388); + setState(405); _errHandler.sync(this); _la = _input.LA(1); } @@ -2588,7 +2683,7 @@ public final JoinRelationContext joinRelation() throws RecognitionException { enterRule(_localctx, 38, RULE_joinRelation); int _la; try { - setState(400); + setState(417); _errHandler.sync(this); switch (_input.LA(1)) { case FULL: @@ -2599,19 +2694,19 @@ public final JoinRelationContext joinRelation() throws RecognitionException { enterOuterAlt(_localctx, 1); { { - setState(389); + setState(406); joinType(); } - setState(390); + setState(407); match(JOIN); - setState(391); + setState(408); ((JoinRelationContext)_localctx).right = relationPrimary(); - setState(393); + setState(410); _errHandler.sync(this); _la = _input.LA(1); if (_la==ON || _la==USING) { { - setState(392); + setState(409); joinCriteria(); } } @@ -2621,13 +2716,13 @@ public final JoinRelationContext joinRelation() throws RecognitionException { case NATURAL: enterOuterAlt(_localctx, 2); { - setState(395); + setState(412); match(NATURAL); - setState(396); + setState(413); joinType(); - setState(397); + setState(414); match(JOIN); - setState(398); + setState(415); ((JoinRelationContext)_localctx).right = relationPrimary(); } break; @@ -2676,19 +2771,19 @@ public final JoinTypeContext joinType() throws RecognitionException { enterRule(_localctx, 40, RULE_joinType); int _la; try { - setState(417); + setState(434); _errHandler.sync(this); switch (_input.LA(1)) { case INNER: case JOIN: enterOuterAlt(_localctx, 1); { - setState(403); + setState(420); _errHandler.sync(this); _la = _input.LA(1); if (_la==INNER) { { - setState(402); + setState(419); match(INNER); } } @@ -2698,14 +2793,14 @@ public final JoinTypeContext joinType() throws RecognitionException { case LEFT: enterOuterAlt(_localctx, 2); { - setState(405); + setState(422); match(LEFT); - setState(407); + setState(424); _errHandler.sync(this); _la = _input.LA(1); if (_la==OUTER) { { - setState(406); + setState(423); match(OUTER); } } @@ -2715,14 +2810,14 @@ public final JoinTypeContext joinType() throws RecognitionException { case RIGHT: enterOuterAlt(_localctx, 3); { - setState(409); + setState(426); match(RIGHT); - setState(411); + setState(428); _errHandler.sync(this); _la = _input.LA(1); if (_la==OUTER) { { - setState(410); + setState(427); match(OUTER); } } @@ -2732,14 +2827,14 @@ public final JoinTypeContext joinType() throws RecognitionException { case FULL: enterOuterAlt(_localctx, 4); { - setState(413); + setState(430); match(FULL); - setState(415); + setState(432); _errHandler.sync(this); _la = _input.LA(1); if (_la==OUTER) { { - setState(414); + setState(431); match(OUTER); } } @@ -2797,44 +2892,44 @@ public final JoinCriteriaContext joinCriteria() throws RecognitionException { enterRule(_localctx, 42, RULE_joinCriteria); int _la; try { - setState(433); + setState(450); _errHandler.sync(this); switch (_input.LA(1)) { case ON: enterOuterAlt(_localctx, 1); { - setState(419); + setState(436); match(ON); - setState(420); + setState(437); booleanExpression(0); } break; case USING: enterOuterAlt(_localctx, 2); { - setState(421); + setState(438); match(USING); - setState(422); + setState(439); match(T__0); - setState(423); + setState(440); identifier(); - setState(428); + setState(445); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(424); + setState(441); match(T__2); - setState(425); + setState(442); identifier(); } } - setState(430); + setState(447); _errHandler.sync(this); _la = _input.LA(1); } - setState(431); + setState(448); match(T__1); } break; @@ -2940,41 +3035,41 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio enterRule(_localctx, 44, RULE_relationPrimary); int _la; try { - setState(463); + setState(480); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,65,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,69,_ctx) ) { case 1: _localctx = new TableNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(436); + setState(453); _errHandler.sync(this); _la = _input.LA(1); if (_la==FROZEN) { { - setState(435); + setState(452); match(FROZEN); } } - setState(438); + setState(455); tableIdentifier(); - setState(443); + setState(460); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,60,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,64,_ctx) ) { case 1: { - setState(440); + setState(457); _errHandler.sync(this); _la = _input.LA(1); if (_la==AS) { { - setState(439); + setState(456); match(AS); } } - setState(442); + setState(459); qualifiedName(); } break; @@ -2985,28 +3080,28 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio _localctx = new AliasedQueryContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(445); + setState(462); match(T__0); - setState(446); + setState(463); queryNoWith(); - setState(447); + setState(464); match(T__1); - setState(452); + setState(469); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,62,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,66,_ctx) ) { case 1: { - setState(449); + setState(466); _errHandler.sync(this); _la = _input.LA(1); if (_la==AS) { { - setState(448); + setState(465); match(AS); } } - setState(451); + setState(468); qualifiedName(); } break; @@ -3017,28 +3112,28 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio _localctx = new AliasedRelationContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(454); + setState(471); match(T__0); - setState(455); + setState(472); relation(); - setState(456); + setState(473); match(T__1); - setState(461); + setState(478); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,64,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,68,_ctx) ) { case 1: { - setState(458); + setState(475); _errHandler.sync(this); _la = _input.LA(1); if (_la==AS) { { - setState(457); + setState(474); match(AS); } } - setState(460); + setState(477); qualifiedName(); } break; @@ -3099,25 +3194,25 @@ public final PivotClauseContext pivotClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(465); + setState(482); match(PIVOT); - setState(466); + setState(483); match(T__0); - setState(467); + setState(484); ((PivotClauseContext)_localctx).aggs = pivotArgs(); - setState(468); + setState(485); match(FOR); - setState(469); + setState(486); ((PivotClauseContext)_localctx).column = qualifiedName(); - setState(470); + setState(487); match(IN); - setState(471); + setState(488); match(T__0); - setState(472); + setState(489); ((PivotClauseContext)_localctx).vals = pivotArgs(); - setState(473); + setState(490); match(T__1); - setState(474); + setState(491); match(T__1); } } @@ -3165,21 +3260,21 @@ public final PivotArgsContext pivotArgs() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(476); + setState(493); namedValueExpression(); - setState(481); + setState(498); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(477); + setState(494); match(T__2); - setState(478); + setState(495); namedValueExpression(); } } - setState(483); + setState(500); _errHandler.sync(this); _la = _input.LA(1); } @@ -3230,24 +3325,24 @@ public final NamedValueExpressionContext namedValueExpression() throws Recogniti try { enterOuterAlt(_localctx, 1); { - setState(484); + setState(501); valueExpression(0); - setState(489); + setState(506); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LIMIT) | (1L << MAPPED) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (OPTIMIZED - 70)) | (1L << (PARSED - 70)) | (1L << (PHYSICAL - 70)) | (1L << (PIVOT - 70)) | (1L << (PLAN - 70)) | (1L << (RLIKE - 70)) | (1L << (QUERY - 70)) | (1L << (SCHEMAS - 70)) | (1L << (SECOND - 70)) | (1L << (SHOW - 70)) | (1L << (SYS - 70)) | (1L << (TABLES - 70)) | (1L << (TEXT - 70)) | (1L << (TOP - 70)) | (1L << (TYPE - 70)) | (1L << (TYPES - 70)) | (1L << (VERIFY - 70)) | (1L << (YEAR - 70)) | (1L << (IDENTIFIER - 70)) | (1L << (DIGIT_IDENTIFIER - 70)) | (1L << (QUOTED_IDENTIFIER - 70)))) != 0) || _la==BACKQUOTED_IDENTIFIER) { { - setState(486); + setState(503); _errHandler.sync(this); _la = _input.LA(1); if (_la==AS) { { - setState(485); + setState(502); match(AS); } } - setState(488); + setState(505); identifier(); } } @@ -3294,7 +3389,7 @@ public final ExpressionContext expression() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(491); + setState(508); booleanExpression(0); } } @@ -3502,18 +3597,18 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(524); + setState(541); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,69,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,73,_ctx) ) { case 1: { _localctx = new LogicalNotContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(494); + setState(511); match(NOT); - setState(495); + setState(512); booleanExpression(8); } break; @@ -3522,13 +3617,13 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new ExistsContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(496); + setState(513); match(EXISTS); - setState(497); + setState(514); match(T__0); - setState(498); + setState(515); query(); - setState(499); + setState(516); match(T__1); } break; @@ -3537,15 +3632,15 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new StringQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(501); + setState(518); match(QUERY); - setState(502); + setState(519); match(T__0); - setState(503); + setState(520); ((StringQueryContext)_localctx).queryString = string(); - setState(504); + setState(521); matchQueryOptions(); - setState(505); + setState(522); match(T__1); } break; @@ -3554,19 +3649,19 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new MatchQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(507); + setState(524); match(MATCH); - setState(508); + setState(525); match(T__0); - setState(509); + setState(526); ((MatchQueryContext)_localctx).singleField = qualifiedName(); - setState(510); + setState(527); match(T__2); - setState(511); + setState(528); ((MatchQueryContext)_localctx).queryString = string(); - setState(512); + setState(529); matchQueryOptions(); - setState(513); + setState(530); match(T__1); } break; @@ -3575,19 +3670,19 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new MultiMatchQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(515); + setState(532); match(MATCH); - setState(516); + setState(533); match(T__0); - setState(517); + setState(534); ((MultiMatchQueryContext)_localctx).multiFields = string(); - setState(518); + setState(535); match(T__2); - setState(519); + setState(536); ((MultiMatchQueryContext)_localctx).queryString = string(); - setState(520); + setState(537); matchQueryOptions(); - setState(521); + setState(538); match(T__1); } break; @@ -3596,33 +3691,33 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(523); + setState(540); predicated(); } break; } _ctx.stop = _input.LT(-1); - setState(534); + setState(551); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,71,_ctx); + _alt = getInterpreter().adaptivePredict(_input,75,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(532); + setState(549); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,70,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,74,_ctx) ) { case 1: { _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(526); + setState(543); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(527); + setState(544); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(528); + setState(545); ((LogicalBinaryContext)_localctx).right = booleanExpression(3); } break; @@ -3631,20 +3726,20 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(529); + setState(546); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(530); + setState(547); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(531); + setState(548); ((LogicalBinaryContext)_localctx).right = booleanExpression(2); } break; } } } - setState(536); + setState(553); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,71,_ctx); + _alt = getInterpreter().adaptivePredict(_input,75,_ctx); } } } @@ -3692,19 +3787,19 @@ public final MatchQueryOptionsContext matchQueryOptions() throws RecognitionExce try { enterOuterAlt(_localctx, 1); { - setState(541); + setState(558); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(537); + setState(554); match(T__2); - setState(538); + setState(555); string(); } } - setState(543); + setState(560); _errHandler.sync(this); _la = _input.LA(1); } @@ -3753,14 +3848,14 @@ public final PredicatedContext predicated() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(544); + setState(561); valueExpression(0); - setState(546); + setState(563); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,73,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,77,_ctx) ) { case 1: { - setState(545); + setState(562); predicate(); } break; @@ -3830,148 +3925,148 @@ public final PredicateContext predicate() throws RecognitionException { enterRule(_localctx, 60, RULE_predicate); int _la; try { - setState(594); + setState(611); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,81,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,85,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(549); + setState(566); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(548); + setState(565); match(NOT); } } - setState(551); + setState(568); ((PredicateContext)_localctx).kind = match(BETWEEN); - setState(552); + setState(569); ((PredicateContext)_localctx).lower = valueExpression(0); - setState(553); + setState(570); match(AND); - setState(554); + setState(571); ((PredicateContext)_localctx).upper = valueExpression(0); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(557); + setState(574); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(556); + setState(573); match(NOT); } } - setState(559); + setState(576); ((PredicateContext)_localctx).kind = match(IN); - setState(560); + setState(577); match(T__0); - setState(561); + setState(578); valueExpression(0); - setState(566); + setState(583); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(562); + setState(579); match(T__2); - setState(563); + setState(580); valueExpression(0); } } - setState(568); + setState(585); _errHandler.sync(this); _la = _input.LA(1); } - setState(569); + setState(586); match(T__1); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(572); + setState(589); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(571); + setState(588); match(NOT); } } - setState(574); + setState(591); ((PredicateContext)_localctx).kind = match(IN); - setState(575); + setState(592); match(T__0); - setState(576); + setState(593); query(); - setState(577); + setState(594); match(T__1); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(580); + setState(597); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(579); + setState(596); match(NOT); } } - setState(582); + setState(599); ((PredicateContext)_localctx).kind = match(LIKE); - setState(583); + setState(600); pattern(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(585); + setState(602); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(584); + setState(601); match(NOT); } } - setState(587); + setState(604); ((PredicateContext)_localctx).kind = match(RLIKE); - setState(588); + setState(605); ((PredicateContext)_localctx).regex = string(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(589); + setState(606); match(IS); - setState(591); + setState(608); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(590); + setState(607); match(NOT); } } - setState(593); + setState(610); ((PredicateContext)_localctx).kind = match(NULL); } break; @@ -4018,9 +4113,9 @@ public final LikePatternContext likePattern() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(596); + setState(613); match(LIKE); - setState(597); + setState(614); pattern(); } } @@ -4068,14 +4163,14 @@ public final PatternContext pattern() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(599); + setState(616); ((PatternContext)_localctx).value = string(); - setState(601); + setState(618); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,82,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,86,_ctx) ) { case 1: { - setState(600); + setState(617); patternEscape(); } break; @@ -4124,26 +4219,26 @@ public final PatternEscapeContext patternEscape() throws RecognitionException { PatternEscapeContext _localctx = new PatternEscapeContext(_ctx, getState()); enterRule(_localctx, 66, RULE_patternEscape); try { - setState(609); + setState(626); _errHandler.sync(this); switch (_input.LA(1)) { case ESCAPE: enterOuterAlt(_localctx, 1); { - setState(603); + setState(620); match(ESCAPE); - setState(604); + setState(621); ((PatternEscapeContext)_localctx).escape = string(); } break; case ESCAPE_ESC: enterOuterAlt(_localctx, 2); { - setState(605); + setState(622); match(ESCAPE_ESC); - setState(606); + setState(623); ((PatternEscapeContext)_localctx).escape = string(); - setState(607); + setState(624); match(ESC_END); } break; @@ -4288,7 +4383,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti int _alt; enterOuterAlt(_localctx, 1); { - setState(615); + setState(632); _errHandler.sync(this); switch (_input.LA(1)) { case T__0: @@ -4361,7 +4456,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _ctx = _localctx; _prevctx = _localctx; - setState(612); + setState(629); primaryExpression(0); } break; @@ -4371,7 +4466,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(613); + setState(630); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -4382,7 +4477,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _errHandler.reportMatch(this); consume(); } - setState(614); + setState(631); valueExpression(4); } break; @@ -4390,25 +4485,25 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(629); + setState(646); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,86,_ctx); + _alt = getInterpreter().adaptivePredict(_input,90,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(627); + setState(644); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,85,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,89,_ctx) ) { case 1: { _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(617); + setState(634); if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(618); + setState(635); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(((((_la - 121)) & ~0x3f) == 0 && ((1L << (_la - 121)) & ((1L << (ASTERISK - 121)) | (1L << (SLASH - 121)) | (1L << (PERCENT - 121)))) != 0)) ) { @@ -4419,7 +4514,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _errHandler.reportMatch(this); consume(); } - setState(619); + setState(636); ((ArithmeticBinaryContext)_localctx).right = valueExpression(4); } break; @@ -4428,9 +4523,9 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(620); + setState(637); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(621); + setState(638); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -4441,7 +4536,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _errHandler.reportMatch(this); consume(); } - setState(622); + setState(639); ((ArithmeticBinaryContext)_localctx).right = valueExpression(3); } break; @@ -4450,20 +4545,20 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ComparisonContext(new ValueExpressionContext(_parentctx, _parentState)); ((ComparisonContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(623); + setState(640); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(624); + setState(641); comparisonOperator(); - setState(625); + setState(642); ((ComparisonContext)_localctx).right = valueExpression(2); } break; } } } - setState(631); + setState(648); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,86,_ctx); + _alt = getInterpreter().adaptivePredict(_input,90,_ctx); } } } @@ -4735,16 +4830,16 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(668); + setState(685); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,91,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,95,_ctx) ) { case 1: { _localctx = new CastContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(633); + setState(650); castExpression(); } break; @@ -4753,7 +4848,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new ExtractContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(634); + setState(651); extractExpression(); } break; @@ -4762,7 +4857,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new CurrentDateTimeFunctionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(635); + setState(652); builtinDateTimeFunction(); } break; @@ -4771,7 +4866,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new ConstantDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(636); + setState(653); constant(); } break; @@ -4780,19 +4875,19 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new StarContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(640); + setState(657); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LIMIT) | (1L << MAPPED) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (OPTIMIZED - 70)) | (1L << (PARSED - 70)) | (1L << (PHYSICAL - 70)) | (1L << (PIVOT - 70)) | (1L << (PLAN - 70)) | (1L << (RLIKE - 70)) | (1L << (QUERY - 70)) | (1L << (SCHEMAS - 70)) | (1L << (SECOND - 70)) | (1L << (SHOW - 70)) | (1L << (SYS - 70)) | (1L << (TABLES - 70)) | (1L << (TEXT - 70)) | (1L << (TOP - 70)) | (1L << (TYPE - 70)) | (1L << (TYPES - 70)) | (1L << (VERIFY - 70)) | (1L << (YEAR - 70)) | (1L << (IDENTIFIER - 70)) | (1L << (DIGIT_IDENTIFIER - 70)) | (1L << (QUOTED_IDENTIFIER - 70)))) != 0) || _la==BACKQUOTED_IDENTIFIER) { { - setState(637); + setState(654); qualifiedName(); - setState(638); + setState(655); match(DOT); } } - setState(642); + setState(659); match(ASTERISK); } break; @@ -4801,7 +4896,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new FunctionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(643); + setState(660); functionExpression(); } break; @@ -4810,11 +4905,11 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new SubqueryExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(644); + setState(661); match(T__0); - setState(645); + setState(662); query(); - setState(646); + setState(663); match(T__1); } break; @@ -4823,7 +4918,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new DereferenceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(648); + setState(665); qualifiedName(); } break; @@ -4832,11 +4927,11 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new ParenthesizedExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(649); + setState(666); match(T__0); - setState(650); + setState(667); expression(); - setState(651); + setState(668); match(T__1); } break; @@ -4845,53 +4940,53 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new CaseContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(653); + setState(670); match(CASE); - setState(655); + setState(672); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CASE) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CONVERT) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LEFT) | (1L << LIMIT) | (1L << MAPPED) | (1L << MATCH) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 66)) & ~0x3f) == 0 && ((1L << (_la - 66)) & ((1L << (NOT - 66)) | (1L << (NULL - 66)) | (1L << (OPTIMIZED - 66)) | (1L << (PARSED - 66)) | (1L << (PHYSICAL - 66)) | (1L << (PIVOT - 66)) | (1L << (PLAN - 66)) | (1L << (RIGHT - 66)) | (1L << (RLIKE - 66)) | (1L << (QUERY - 66)) | (1L << (SCHEMAS - 66)) | (1L << (SECOND - 66)) | (1L << (SHOW - 66)) | (1L << (SYS - 66)) | (1L << (TABLES - 66)) | (1L << (TEXT - 66)) | (1L << (TRUE - 66)) | (1L << (TOP - 66)) | (1L << (TYPE - 66)) | (1L << (TYPES - 66)) | (1L << (VERIFY - 66)) | (1L << (YEAR - 66)) | (1L << (FUNCTION_ESC - 66)) | (1L << (DATE_ESC - 66)) | (1L << (TIME_ESC - 66)) | (1L << (TIMESTAMP_ESC - 66)) | (1L << (GUID_ESC - 66)) | (1L << (PLUS - 66)) | (1L << (MINUS - 66)) | (1L << (ASTERISK - 66)) | (1L << (PARAM - 66)) | (1L << (STRING - 66)) | (1L << (INTEGER_VALUE - 66)) | (1L << (DECIMAL_VALUE - 66)))) != 0) || ((((_la - 130)) & ~0x3f) == 0 && ((1L << (_la - 130)) & ((1L << (IDENTIFIER - 130)) | (1L << (DIGIT_IDENTIFIER - 130)) | (1L << (QUOTED_IDENTIFIER - 130)) | (1L << (BACKQUOTED_IDENTIFIER - 130)))) != 0)) { { - setState(654); + setState(671); ((CaseContext)_localctx).operand = booleanExpression(0); } } - setState(658); + setState(675); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(657); + setState(674); whenClause(); } } - setState(660); + setState(677); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==WHEN ); - setState(664); + setState(681); _errHandler.sync(this); _la = _input.LA(1); if (_la==ELSE) { { - setState(662); + setState(679); match(ELSE); - setState(663); + setState(680); ((CaseContext)_localctx).elseClause = booleanExpression(0); } } - setState(666); + setState(683); match(END); } break; } _ctx.stop = _input.LT(-1); - setState(675); + setState(692); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,92,_ctx); + _alt = getInterpreter().adaptivePredict(_input,96,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); @@ -4900,18 +4995,18 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc { _localctx = new CastOperatorExpressionContext(new PrimaryExpressionContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_primaryExpression); - setState(670); + setState(687); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); - setState(671); + setState(688); match(CAST_OP); - setState(672); + setState(689); dataType(); } } } - setState(677); + setState(694); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,92,_ctx); + _alt = getInterpreter().adaptivePredict(_input,96,_ctx); } } } @@ -4954,27 +5049,27 @@ public final BuiltinDateTimeFunctionContext builtinDateTimeFunction() throws Rec BuiltinDateTimeFunctionContext _localctx = new BuiltinDateTimeFunctionContext(_ctx, getState()); enterRule(_localctx, 72, RULE_builtinDateTimeFunction); try { - setState(681); + setState(698); _errHandler.sync(this); switch (_input.LA(1)) { case CURRENT_TIMESTAMP: enterOuterAlt(_localctx, 1); { - setState(678); + setState(695); ((BuiltinDateTimeFunctionContext)_localctx).name = match(CURRENT_TIMESTAMP); } break; case CURRENT_DATE: enterOuterAlt(_localctx, 2); { - setState(679); + setState(696); ((BuiltinDateTimeFunctionContext)_localctx).name = match(CURRENT_DATE); } break; case CURRENT_TIME: enterOuterAlt(_localctx, 3); { - setState(680); + setState(697); ((BuiltinDateTimeFunctionContext)_localctx).name = match(CURRENT_TIME); } break; @@ -5025,42 +5120,42 @@ public final CastExpressionContext castExpression() throws RecognitionException CastExpressionContext _localctx = new CastExpressionContext(_ctx, getState()); enterRule(_localctx, 74, RULE_castExpression); try { - setState(693); + setState(710); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,94,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,98,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(683); + setState(700); castTemplate(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(684); + setState(701); match(FUNCTION_ESC); - setState(685); + setState(702); castTemplate(); - setState(686); + setState(703); match(ESC_END); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(688); + setState(705); convertTemplate(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(689); + setState(706); match(FUNCTION_ESC); - setState(690); + setState(707); convertTemplate(); - setState(691); + setState(708); match(ESC_END); } break; @@ -5111,17 +5206,17 @@ public final CastTemplateContext castTemplate() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(695); + setState(712); match(CAST); - setState(696); + setState(713); match(T__0); - setState(697); + setState(714); expression(); - setState(698); + setState(715); match(AS); - setState(699); + setState(716); dataType(); - setState(700); + setState(717); match(T__1); } } @@ -5169,17 +5264,17 @@ public final ConvertTemplateContext convertTemplate() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(702); + setState(719); match(CONVERT); - setState(703); + setState(720); match(T__0); - setState(704); + setState(721); expression(); - setState(705); + setState(722); match(T__2); - setState(706); + setState(723); dataType(); - setState(707); + setState(724); match(T__1); } } @@ -5223,24 +5318,24 @@ public final ExtractExpressionContext extractExpression() throws RecognitionExce ExtractExpressionContext _localctx = new ExtractExpressionContext(_ctx, getState()); enterRule(_localctx, 80, RULE_extractExpression); try { - setState(714); + setState(731); _errHandler.sync(this); switch (_input.LA(1)) { case EXTRACT: enterOuterAlt(_localctx, 1); { - setState(709); + setState(726); extractTemplate(); } break; case FUNCTION_ESC: enterOuterAlt(_localctx, 2); { - setState(710); + setState(727); match(FUNCTION_ESC); - setState(711); + setState(728); extractTemplate(); - setState(712); + setState(729); match(ESC_END); } break; @@ -5294,17 +5389,17 @@ public final ExtractTemplateContext extractTemplate() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(716); + setState(733); match(EXTRACT); - setState(717); + setState(734); match(T__0); - setState(718); + setState(735); ((ExtractTemplateContext)_localctx).field = identifier(); - setState(719); + setState(736); match(FROM); - setState(720); + setState(737); valueExpression(0); - setState(721); + setState(738); match(T__1); } } @@ -5348,7 +5443,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx FunctionExpressionContext _localctx = new FunctionExpressionContext(_ctx, getState()); enterRule(_localctx, 84, RULE_functionExpression); try { - setState(728); + setState(745); _errHandler.sync(this); switch (_input.LA(1)) { case ANALYZE: @@ -5400,18 +5495,18 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 1); { - setState(723); + setState(740); functionTemplate(); } break; case FUNCTION_ESC: enterOuterAlt(_localctx, 2); { - setState(724); + setState(741); match(FUNCTION_ESC); - setState(725); + setState(742); functionTemplate(); - setState(726); + setState(743); match(ESC_END); } break; @@ -5469,47 +5564,47 @@ public final FunctionTemplateContext functionTemplate() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(730); + setState(747); functionName(); - setState(731); + setState(748); match(T__0); - setState(743); + setState(760); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ALL) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CASE) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CONVERT) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << DISTINCT) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LEFT) | (1L << LIMIT) | (1L << MAPPED) | (1L << MATCH) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 66)) & ~0x3f) == 0 && ((1L << (_la - 66)) & ((1L << (NOT - 66)) | (1L << (NULL - 66)) | (1L << (OPTIMIZED - 66)) | (1L << (PARSED - 66)) | (1L << (PHYSICAL - 66)) | (1L << (PIVOT - 66)) | (1L << (PLAN - 66)) | (1L << (RIGHT - 66)) | (1L << (RLIKE - 66)) | (1L << (QUERY - 66)) | (1L << (SCHEMAS - 66)) | (1L << (SECOND - 66)) | (1L << (SHOW - 66)) | (1L << (SYS - 66)) | (1L << (TABLES - 66)) | (1L << (TEXT - 66)) | (1L << (TRUE - 66)) | (1L << (TOP - 66)) | (1L << (TYPE - 66)) | (1L << (TYPES - 66)) | (1L << (VERIFY - 66)) | (1L << (YEAR - 66)) | (1L << (FUNCTION_ESC - 66)) | (1L << (DATE_ESC - 66)) | (1L << (TIME_ESC - 66)) | (1L << (TIMESTAMP_ESC - 66)) | (1L << (GUID_ESC - 66)) | (1L << (PLUS - 66)) | (1L << (MINUS - 66)) | (1L << (ASTERISK - 66)) | (1L << (PARAM - 66)) | (1L << (STRING - 66)) | (1L << (INTEGER_VALUE - 66)) | (1L << (DECIMAL_VALUE - 66)))) != 0) || ((((_la - 130)) & ~0x3f) == 0 && ((1L << (_la - 130)) & ((1L << (IDENTIFIER - 130)) | (1L << (DIGIT_IDENTIFIER - 130)) | (1L << (QUOTED_IDENTIFIER - 130)) | (1L << (BACKQUOTED_IDENTIFIER - 130)))) != 0)) { { - setState(733); + setState(750); _errHandler.sync(this); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(732); + setState(749); setQuantifier(); } } - setState(735); + setState(752); expression(); - setState(740); + setState(757); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(736); + setState(753); match(T__2); - setState(737); + setState(754); expression(); } } - setState(742); + setState(759); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(745); + setState(762); match(T__1); } } @@ -5553,20 +5648,20 @@ public final FunctionNameContext functionName() throws RecognitionException { FunctionNameContext _localctx = new FunctionNameContext(_ctx, getState()); enterRule(_localctx, 88, RULE_functionName); try { - setState(750); + setState(767); _errHandler.sync(this); switch (_input.LA(1)) { case LEFT: enterOuterAlt(_localctx, 1); { - setState(747); + setState(764); match(LEFT); } break; case RIGHT: enterOuterAlt(_localctx, 2); { - setState(748); + setState(765); match(RIGHT); } break; @@ -5617,7 +5712,7 @@ public final FunctionNameContext functionName() throws RecognitionException { case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 3); { - setState(749); + setState(766); identifier(); } break; @@ -5848,14 +5943,14 @@ public final ConstantContext constant() throws RecognitionException { enterRule(_localctx, 90, RULE_constant); try { int _alt; - setState(778); + setState(795); _errHandler.sync(this); switch (_input.LA(1)) { case NULL: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(752); + setState(769); match(NULL); } break; @@ -5863,7 +5958,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new IntervalLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(753); + setState(770); interval(); } break; @@ -5872,7 +5967,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(754); + setState(771); number(); } break; @@ -5881,7 +5976,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(755); + setState(772); booleanValue(); } break; @@ -5889,7 +5984,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(757); + setState(774); _errHandler.sync(this); _alt = 1; do { @@ -5897,7 +5992,7 @@ public final ConstantContext constant() throws RecognitionException { case 1: { { - setState(756); + setState(773); match(STRING); } } @@ -5905,9 +6000,9 @@ public final ConstantContext constant() throws RecognitionException { default: throw new NoViableAltException(this); } - setState(759); + setState(776); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,101,_ctx); + _alt = getInterpreter().adaptivePredict(_input,105,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); } break; @@ -5915,7 +6010,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new ParamLiteralContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(761); + setState(778); match(PARAM); } break; @@ -5923,11 +6018,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new DateEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(762); + setState(779); match(DATE_ESC); - setState(763); + setState(780); string(); - setState(764); + setState(781); match(ESC_END); } break; @@ -5935,11 +6030,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new TimeEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(766); + setState(783); match(TIME_ESC); - setState(767); + setState(784); string(); - setState(768); + setState(785); match(ESC_END); } break; @@ -5947,11 +6042,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new TimestampEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(770); + setState(787); match(TIMESTAMP_ESC); - setState(771); + setState(788); string(); - setState(772); + setState(789); match(ESC_END); } break; @@ -5959,11 +6054,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new GuidEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(774); + setState(791); match(GUID_ESC); - setState(775); + setState(792); string(); - setState(776); + setState(793); match(ESC_END); } break; @@ -6016,7 +6111,7 @@ public final ComparisonOperatorContext comparisonOperator() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(780); + setState(797); _la = _input.LA(1); if ( !(((((_la - 112)) & ~0x3f) == 0 && ((1L << (_la - 112)) & ((1L << (EQ - 112)) | (1L << (NULLEQ - 112)) | (1L << (NEQ - 112)) | (1L << (LT - 112)) | (1L << (LTE - 112)) | (1L << (GT - 112)) | (1L << (GTE - 112)))) != 0)) ) { _errHandler.recoverInline(this); @@ -6068,7 +6163,7 @@ public final BooleanValueContext booleanValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(782); + setState(799); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -6139,14 +6234,14 @@ public final IntervalContext interval() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(784); + setState(801); match(INTERVAL); - setState(786); + setState(803); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(785); + setState(802); ((IntervalContext)_localctx).sign = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -6160,36 +6255,36 @@ public final IntervalContext interval() throws RecognitionException { } } - setState(790); + setState(807); _errHandler.sync(this); switch (_input.LA(1)) { case INTEGER_VALUE: case DECIMAL_VALUE: { - setState(788); + setState(805); ((IntervalContext)_localctx).valueNumeric = number(); } break; case PARAM: case STRING: { - setState(789); + setState(806); ((IntervalContext)_localctx).valuePattern = string(); } break; default: throw new NoViableAltException(this); } - setState(792); + setState(809); ((IntervalContext)_localctx).leading = intervalField(); - setState(795); + setState(812); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,105,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,109,_ctx) ) { case 1: { - setState(793); + setState(810); match(TO); - setState(794); + setState(811); ((IntervalContext)_localctx).trailing = intervalField(); } break; @@ -6246,7 +6341,7 @@ public final IntervalFieldContext intervalField() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(797); + setState(814); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << DAY) | (1L << DAYS) | (1L << HOUR) | (1L << HOURS) | (1L << MINUTE) | (1L << MINUTES) | (1L << MONTH))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (MONTHS - 64)) | (1L << (SECOND - 64)) | (1L << (SECONDS - 64)) | (1L << (YEAR - 64)) | (1L << (YEARS - 64)))) != 0)) ) { _errHandler.recoverInline(this); @@ -6307,7 +6402,7 @@ public final DataTypeContext dataType() throws RecognitionException { _localctx = new PrimitiveDataTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(799); + setState(816); identifier(); } } @@ -6359,25 +6454,25 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(806); + setState(823); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,106,_ctx); + _alt = getInterpreter().adaptivePredict(_input,110,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(801); + setState(818); identifier(); - setState(802); + setState(819); match(DOT); } } } - setState(808); + setState(825); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,106,_ctx); + _alt = getInterpreter().adaptivePredict(_input,110,_ctx); } - setState(809); + setState(826); identifier(); } } @@ -6422,14 +6517,14 @@ public final IdentifierContext identifier() throws RecognitionException { IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); enterRule(_localctx, 104, RULE_identifier); try { - setState(813); + setState(830); _errHandler.sync(this); switch (_input.LA(1)) { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 1); { - setState(811); + setState(828); quoteIdentifier(); } break; @@ -6478,7 +6573,7 @@ public final IdentifierContext identifier() throws RecognitionException { case DIGIT_IDENTIFIER: enterOuterAlt(_localctx, 2); { - setState(812); + setState(829); unquoteIdentifier(); } break; @@ -6531,44 +6626,44 @@ public final TableIdentifierContext tableIdentifier() throws RecognitionExceptio enterRule(_localctx, 106, RULE_tableIdentifier); int _la; try { - setState(827); + setState(844); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,110,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,114,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(818); + setState(835); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LIMIT) | (1L << MAPPED) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (OPTIMIZED - 70)) | (1L << (PARSED - 70)) | (1L << (PHYSICAL - 70)) | (1L << (PIVOT - 70)) | (1L << (PLAN - 70)) | (1L << (RLIKE - 70)) | (1L << (QUERY - 70)) | (1L << (SCHEMAS - 70)) | (1L << (SECOND - 70)) | (1L << (SHOW - 70)) | (1L << (SYS - 70)) | (1L << (TABLES - 70)) | (1L << (TEXT - 70)) | (1L << (TOP - 70)) | (1L << (TYPE - 70)) | (1L << (TYPES - 70)) | (1L << (VERIFY - 70)) | (1L << (YEAR - 70)) | (1L << (IDENTIFIER - 70)) | (1L << (DIGIT_IDENTIFIER - 70)) | (1L << (QUOTED_IDENTIFIER - 70)))) != 0) || _la==BACKQUOTED_IDENTIFIER) { { - setState(815); + setState(832); ((TableIdentifierContext)_localctx).catalog = identifier(); - setState(816); + setState(833); match(T__3); } } - setState(820); + setState(837); match(TABLE_IDENTIFIER); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(824); + setState(841); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,109,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,113,_ctx) ) { case 1: { - setState(821); + setState(838); ((TableIdentifierContext)_localctx).catalog = identifier(); - setState(822); + setState(839); match(T__3); } break; } - setState(826); + setState(843); ((TableIdentifierContext)_localctx).name = identifier(); } break; @@ -6635,14 +6730,14 @@ public final QuoteIdentifierContext quoteIdentifier() throws RecognitionExceptio QuoteIdentifierContext _localctx = new QuoteIdentifierContext(_ctx, getState()); enterRule(_localctx, 108, RULE_quoteIdentifier); try { - setState(831); + setState(848); _errHandler.sync(this); switch (_input.LA(1)) { case QUOTED_IDENTIFIER: _localctx = new QuotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(829); + setState(846); match(QUOTED_IDENTIFIER); } break; @@ -6650,7 +6745,7 @@ public final QuoteIdentifierContext quoteIdentifier() throws RecognitionExceptio _localctx = new BackQuotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(830); + setState(847); match(BACKQUOTED_IDENTIFIER); } break; @@ -6722,14 +6817,14 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce UnquoteIdentifierContext _localctx = new UnquoteIdentifierContext(_ctx, getState()); enterRule(_localctx, 110, RULE_unquoteIdentifier); try { - setState(836); + setState(853); _errHandler.sync(this); switch (_input.LA(1)) { case IDENTIFIER: _localctx = new UnquotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(833); + setState(850); match(IDENTIFIER); } break; @@ -6777,7 +6872,7 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce _localctx = new UnquotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(834); + setState(851); nonReserved(); } break; @@ -6785,7 +6880,7 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce _localctx = new DigitIdentifierContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(835); + setState(852); match(DIGIT_IDENTIFIER); } break; @@ -6854,14 +6949,14 @@ public final NumberContext number() throws RecognitionException { NumberContext _localctx = new NumberContext(_ctx, getState()); enterRule(_localctx, 112, RULE_number); try { - setState(840); + setState(857); _errHandler.sync(this); switch (_input.LA(1)) { case DECIMAL_VALUE: _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(838); + setState(855); match(DECIMAL_VALUE); } break; @@ -6869,7 +6964,7 @@ public final NumberContext number() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(839); + setState(856); match(INTEGER_VALUE); } break; @@ -6917,7 +7012,7 @@ public final StringContext string() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(842); + setState(859); _la = _input.LA(1); if ( !(_la==PARAM || _la==STRING) ) { _errHandler.recoverInline(this); @@ -6976,13 +7071,13 @@ public final WhenClauseContext whenClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(844); + setState(861); match(WHEN); - setState(845); + setState(862); ((WhenClauseContext)_localctx).condition = expression(); - setState(846); + setState(863); match(THEN); - setState(847); + setState(864); ((WhenClauseContext)_localctx).result = expression(); } } @@ -7065,7 +7160,7 @@ public final NonReservedContext nonReserved() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(849); + setState(866); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << CURRENT_DATE) | (1L << CURRENT_TIME) | (1L << CURRENT_TIMESTAMP) | (1L << DAY) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FIRST) | (1L << FORMAT) | (1L << FULL) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << HOUR) | (1L << INTERVAL) | (1L << LAST) | (1L << LIMIT) | (1L << MAPPED) | (1L << MINUTE) | (1L << MONTH))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (OPTIMIZED - 70)) | (1L << (PARSED - 70)) | (1L << (PHYSICAL - 70)) | (1L << (PIVOT - 70)) | (1L << (PLAN - 70)) | (1L << (RLIKE - 70)) | (1L << (QUERY - 70)) | (1L << (SCHEMAS - 70)) | (1L << (SECOND - 70)) | (1L << (SHOW - 70)) | (1L << (SYS - 70)) | (1L << (TABLES - 70)) | (1L << (TEXT - 70)) | (1L << (TOP - 70)) | (1L << (TYPE - 70)) | (1L << (TYPES - 70)) | (1L << (VERIFY - 70)) | (1L << (YEAR - 70)))) != 0)) ) { _errHandler.recoverInline(this); @@ -7128,7 +7223,7 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u008d\u0356\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u008d\u0367\4\2\t"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -7139,331 +7234,339 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in "\3\2\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4\u008a"+ "\n\4\f\4\16\4\u008d\13\4\3\4\5\4\u0090\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ "\7\4\u0099\n\4\f\4\16\4\u009c\13\4\3\4\5\4\u009f\n\4\3\4\3\4\3\4\3\4\3"+ - "\4\5\4\u00a6\n\4\3\4\3\4\5\4\u00aa\n\4\3\4\3\4\3\4\3\4\5\4\u00b0\n\4\3"+ - "\4\3\4\3\4\5\4\u00b5\n\4\3\4\3\4\3\4\5\4\u00ba\n\4\3\4\3\4\5\4\u00be\n"+ - "\4\3\4\3\4\3\4\5\4\u00c3\n\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4\u00cb\n\4\3\4"+ - "\3\4\5\4\u00cf\n\4\3\4\3\4\3\4\3\4\7\4\u00d5\n\4\f\4\16\4\u00d8\13\4\5"+ - "\4\u00da\n\4\3\4\3\4\3\4\3\4\5\4\u00e0\n\4\3\4\3\4\3\4\5\4\u00e5\n\4\3"+ - "\4\5\4\u00e8\n\4\3\4\3\4\3\4\5\4\u00ed\n\4\3\4\5\4\u00f0\n\4\5\4\u00f2"+ - "\n\4\3\5\3\5\3\5\3\5\7\5\u00f8\n\5\f\5\16\5\u00fb\13\5\5\5\u00fd\n\5\3"+ - "\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\7\6\u0107\n\6\f\6\16\6\u010a\13\6\5\6\u010c"+ - "\n\6\3\6\5\6\u010f\n\6\3\7\3\7\3\7\3\7\3\7\5\7\u0116\n\7\3\b\3\b\3\b\3"+ - "\b\3\b\5\b\u011d\n\b\3\t\3\t\5\t\u0121\n\t\3\t\3\t\5\t\u0125\n\t\3\n\3"+ - "\n\5\n\u0129\n\n\3\n\5\n\u012c\n\n\3\n\3\n\5\n\u0130\n\n\3\n\3\n\5\n\u0134"+ - "\n\n\3\n\3\n\3\n\5\n\u0139\n\n\3\n\3\n\5\n\u013d\n\n\3\13\3\13\3\13\3"+ - "\13\7\13\u0143\n\13\f\13\16\13\u0146\13\13\3\13\5\13\u0149\n\13\3\f\5"+ - "\f\u014c\n\f\3\f\3\f\3\f\7\f\u0151\n\f\f\f\16\f\u0154\13\f\3\r\3\r\3\16"+ - "\3\16\3\16\3\16\7\16\u015c\n\16\f\16\16\16\u015f\13\16\5\16\u0161\n\16"+ - "\3\16\3\16\5\16\u0165\n\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20"+ - "\3\21\3\21\3\22\3\22\3\22\7\22\u0175\n\22\f\22\16\22\u0178\13\22\3\23"+ - "\3\23\5\23\u017c\n\23\3\23\5\23\u017f\n\23\3\24\3\24\7\24\u0183\n\24\f"+ - "\24\16\24\u0186\13\24\3\25\3\25\3\25\3\25\5\25\u018c\n\25\3\25\3\25\3"+ - "\25\3\25\3\25\5\25\u0193\n\25\3\26\5\26\u0196\n\26\3\26\3\26\5\26\u019a"+ - "\n\26\3\26\3\26\5\26\u019e\n\26\3\26\3\26\5\26\u01a2\n\26\5\26\u01a4\n"+ - "\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\7\27\u01ad\n\27\f\27\16\27\u01b0"+ - "\13\27\3\27\3\27\5\27\u01b4\n\27\3\30\5\30\u01b7\n\30\3\30\3\30\5\30\u01bb"+ - "\n\30\3\30\5\30\u01be\n\30\3\30\3\30\3\30\3\30\5\30\u01c4\n\30\3\30\5"+ - "\30\u01c7\n\30\3\30\3\30\3\30\3\30\5\30\u01cd\n\30\3\30\5\30\u01d0\n\30"+ - "\5\30\u01d2\n\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ - "\3\32\3\32\3\32\7\32\u01e2\n\32\f\32\16\32\u01e5\13\32\3\33\3\33\5\33"+ - "\u01e9\n\33\3\33\5\33\u01ec\n\33\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3"+ + "\4\3\4\5\4\u00a7\n\4\5\4\u00a9\n\4\3\4\3\4\5\4\u00ad\n\4\3\4\3\4\5\4\u00b1"+ + "\n\4\3\4\3\4\3\4\3\4\5\4\u00b7\n\4\3\4\3\4\5\4\u00bb\n\4\3\4\3\4\3\4\5"+ + "\4\u00c0\n\4\3\4\3\4\3\4\5\4\u00c5\n\4\3\4\3\4\5\4\u00c9\n\4\3\4\3\4\5"+ + "\4\u00cd\n\4\3\4\3\4\3\4\5\4\u00d2\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ + "\5\4\u00dc\n\4\3\4\3\4\5\4\u00e0\n\4\3\4\3\4\3\4\3\4\7\4\u00e6\n\4\f\4"+ + "\16\4\u00e9\13\4\5\4\u00eb\n\4\3\4\3\4\3\4\3\4\5\4\u00f1\n\4\3\4\3\4\3"+ + "\4\5\4\u00f6\n\4\3\4\5\4\u00f9\n\4\3\4\3\4\3\4\5\4\u00fe\n\4\3\4\5\4\u0101"+ + "\n\4\5\4\u0103\n\4\3\5\3\5\3\5\3\5\7\5\u0109\n\5\f\5\16\5\u010c\13\5\5"+ + "\5\u010e\n\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\7\6\u0118\n\6\f\6\16\6\u011b"+ + "\13\6\5\6\u011d\n\6\3\6\5\6\u0120\n\6\3\7\3\7\3\7\3\7\3\7\5\7\u0127\n"+ + "\7\3\b\3\b\3\b\3\b\3\b\5\b\u012e\n\b\3\t\3\t\5\t\u0132\n\t\3\t\3\t\5\t"+ + "\u0136\n\t\3\n\3\n\5\n\u013a\n\n\3\n\5\n\u013d\n\n\3\n\3\n\5\n\u0141\n"+ + "\n\3\n\3\n\5\n\u0145\n\n\3\n\3\n\3\n\5\n\u014a\n\n\3\n\3\n\5\n\u014e\n"+ + "\n\3\13\3\13\3\13\3\13\7\13\u0154\n\13\f\13\16\13\u0157\13\13\3\13\5\13"+ + "\u015a\n\13\3\f\5\f\u015d\n\f\3\f\3\f\3\f\7\f\u0162\n\f\f\f\16\f\u0165"+ + "\13\f\3\r\3\r\3\16\3\16\3\16\3\16\7\16\u016d\n\16\f\16\16\16\u0170\13"+ + "\16\5\16\u0172\n\16\3\16\3\16\5\16\u0176\n\16\3\17\3\17\3\17\3\17\3\17"+ + "\3\17\3\20\3\20\3\20\3\21\3\21\3\22\3\22\3\22\7\22\u0186\n\22\f\22\16"+ + "\22\u0189\13\22\3\23\3\23\5\23\u018d\n\23\3\23\5\23\u0190\n\23\3\24\3"+ + "\24\7\24\u0194\n\24\f\24\16\24\u0197\13\24\3\25\3\25\3\25\3\25\5\25\u019d"+ + "\n\25\3\25\3\25\3\25\3\25\3\25\5\25\u01a4\n\25\3\26\5\26\u01a7\n\26\3"+ + "\26\3\26\5\26\u01ab\n\26\3\26\3\26\5\26\u01af\n\26\3\26\3\26\5\26\u01b3"+ + "\n\26\5\26\u01b5\n\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\7\27\u01be\n"+ + "\27\f\27\16\27\u01c1\13\27\3\27\3\27\5\27\u01c5\n\27\3\30\5\30\u01c8\n"+ + "\30\3\30\3\30\5\30\u01cc\n\30\3\30\5\30\u01cf\n\30\3\30\3\30\3\30\3\30"+ + "\5\30\u01d5\n\30\3\30\5\30\u01d8\n\30\3\30\3\30\3\30\3\30\5\30\u01de\n"+ + "\30\3\30\5\30\u01e1\n\30\5\30\u01e3\n\30\3\31\3\31\3\31\3\31\3\31\3\31"+ + "\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\7\32\u01f3\n\32\f\32\16\32\u01f6"+ + "\13\32\3\33\3\33\5\33\u01fa\n\33\3\33\5\33\u01fd\n\33\3\34\3\34\3\35\3"+ + "\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3"+ "\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3"+ - "\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\5\35\u020f"+ - "\n\35\3\35\3\35\3\35\3\35\3\35\3\35\7\35\u0217\n\35\f\35\16\35\u021a\13"+ - "\35\3\36\3\36\7\36\u021e\n\36\f\36\16\36\u0221\13\36\3\37\3\37\5\37\u0225"+ - "\n\37\3 \5 \u0228\n \3 \3 \3 \3 \3 \3 \5 \u0230\n \3 \3 \3 \3 \3 \7 \u0237"+ - "\n \f \16 \u023a\13 \3 \3 \3 \5 \u023f\n \3 \3 \3 \3 \3 \3 \5 \u0247\n"+ - " \3 \3 \3 \5 \u024c\n \3 \3 \3 \3 \5 \u0252\n \3 \5 \u0255\n \3!\3!\3"+ - "!\3\"\3\"\5\"\u025c\n\"\3#\3#\3#\3#\3#\3#\5#\u0264\n#\3$\3$\3$\3$\5$\u026a"+ - "\n$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\7$\u0276\n$\f$\16$\u0279\13$\3%\3%\3"+ - "%\3%\3%\3%\3%\3%\5%\u0283\n%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\5"+ - "%\u0292\n%\3%\6%\u0295\n%\r%\16%\u0296\3%\3%\5%\u029b\n%\3%\3%\5%\u029f"+ - "\n%\3%\3%\3%\7%\u02a4\n%\f%\16%\u02a7\13%\3&\3&\3&\5&\u02ac\n&\3\'\3\'"+ - "\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\5\'\u02b8\n\'\3(\3(\3(\3(\3(\3(\3(\3"+ - ")\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\5*\u02cd\n*\3+\3+\3+\3+\3+\3+\3+\3"+ - ",\3,\3,\3,\3,\5,\u02db\n,\3-\3-\3-\5-\u02e0\n-\3-\3-\3-\7-\u02e5\n-\f"+ - "-\16-\u02e8\13-\5-\u02ea\n-\3-\3-\3.\3.\3.\5.\u02f1\n.\3/\3/\3/\3/\3/"+ - "\6/\u02f8\n/\r/\16/\u02f9\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3"+ - "/\3/\3/\5/\u030d\n/\3\60\3\60\3\61\3\61\3\62\3\62\5\62\u0315\n\62\3\62"+ - "\3\62\5\62\u0319\n\62\3\62\3\62\3\62\5\62\u031e\n\62\3\63\3\63\3\64\3"+ - "\64\3\65\3\65\3\65\7\65\u0327\n\65\f\65\16\65\u032a\13\65\3\65\3\65\3"+ - "\66\3\66\5\66\u0330\n\66\3\67\3\67\3\67\5\67\u0335\n\67\3\67\3\67\3\67"+ - "\3\67\5\67\u033b\n\67\3\67\5\67\u033e\n\67\38\38\58\u0342\n8\39\39\39"+ - "\59\u0347\n9\3:\3:\5:\u034b\n:\3;\3;\3<\3<\3<\3<\3<\3=\3=\3=\2\58FH>\2"+ - "\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJL"+ - "NPRTVXZ\\^`bdfhjlnprtvx\2\22\b\2\7\7\t\t\"\"==HHLL\4\2..[[\4\2\t\tHH\4"+ - "\2**\63\63\3\2\34\35\3\2yz\4\2\7\7\u0082\u0082\4\2\r\r\34\34\4\2\'\'9"+ - "9\4\2\7\7\36\36\3\2{}\3\2rx\4\2&&]]\7\2\31\32\61\62?BTUgh\3\2\u0080\u0081"+ - "\31\2\b\t\23\24\26\31\33\33\"\"$$\'\')),.\61\61\66\6699<=??AAHHLOQTWX"+ - "Z[_accgg\2\u03b9\2z\3\2\2\2\4}\3\2\2\2\6\u00f1\3\2\2\2\b\u00fc\3\2\2\2"+ - "\n\u0100\3\2\2\2\f\u0115\3\2\2\2\16\u011c\3\2\2\2\20\u011e\3\2\2\2\22"+ - "\u0126\3\2\2\2\24\u013e\3\2\2\2\26\u014b\3\2\2\2\30\u0155\3\2\2\2\32\u0164"+ - "\3\2\2\2\34\u0166\3\2\2\2\36\u016c\3\2\2\2 \u016f\3\2\2\2\"\u0171\3\2"+ - "\2\2$\u0179\3\2\2\2&\u0180\3\2\2\2(\u0192\3\2\2\2*\u01a3\3\2\2\2,\u01b3"+ - "\3\2\2\2.\u01d1\3\2\2\2\60\u01d3\3\2\2\2\62\u01de\3\2\2\2\64\u01e6\3\2"+ - "\2\2\66\u01ed\3\2\2\28\u020e\3\2\2\2:\u021f\3\2\2\2<\u0222\3\2\2\2>\u0254"+ - "\3\2\2\2@\u0256\3\2\2\2B\u0259\3\2\2\2D\u0263\3\2\2\2F\u0269\3\2\2\2H"+ - "\u029e\3\2\2\2J\u02ab\3\2\2\2L\u02b7\3\2\2\2N\u02b9\3\2\2\2P\u02c0\3\2"+ - "\2\2R\u02cc\3\2\2\2T\u02ce\3\2\2\2V\u02da\3\2\2\2X\u02dc\3\2\2\2Z\u02f0"+ - "\3\2\2\2\\\u030c\3\2\2\2^\u030e\3\2\2\2`\u0310\3\2\2\2b\u0312\3\2\2\2"+ - "d\u031f\3\2\2\2f\u0321\3\2\2\2h\u0328\3\2\2\2j\u032f\3\2\2\2l\u033d\3"+ - "\2\2\2n\u0341\3\2\2\2p\u0346\3\2\2\2r\u034a\3\2\2\2t\u034c\3\2\2\2v\u034e"+ - "\3\2\2\2x\u0353\3\2\2\2z{\5\6\4\2{|\7\2\2\3|\3\3\2\2\2}~\5\66\34\2~\177"+ - "\7\2\2\3\177\5\3\2\2\2\u0080\u00f2\5\b\5\2\u0081\u008f\7$\2\2\u0082\u008b"+ - "\7\3\2\2\u0083\u0084\7O\2\2\u0084\u008a\t\2\2\2\u0085\u0086\7)\2\2\u0086"+ - "\u008a\t\3\2\2\u0087\u0088\7c\2\2\u0088\u008a\5`\61\2\u0089\u0083\3\2"+ - "\2\2\u0089\u0085\3\2\2\2\u0089\u0087\3\2\2\2\u008a\u008d\3\2\2\2\u008b"+ - "\u0089\3\2\2\2\u008b\u008c\3\2\2\2\u008c\u008e\3\2\2\2\u008d\u008b\3\2"+ - "\2\2\u008e\u0090\7\4\2\2\u008f\u0082\3\2\2\2\u008f\u0090\3\2\2\2\u0090"+ - "\u0091\3\2\2\2\u0091\u00f2\5\6\4\2\u0092\u009e\7\33\2\2\u0093\u009a\7"+ - "\3\2\2\u0094\u0095\7O\2\2\u0095\u0099\t\4\2\2\u0096\u0097\7)\2\2\u0097"+ - "\u0099\t\3\2\2\u0098\u0094\3\2\2\2\u0098\u0096\3\2\2\2\u0099\u009c\3\2"+ - "\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b\u009d\3\2\2\2\u009c"+ - "\u009a\3\2\2\2\u009d\u009f\7\4\2\2\u009e\u0093\3\2\2\2\u009e\u009f\3\2"+ - "\2\2\u009f\u00a0\3\2\2\2\u00a0\u00f2\5\6\4\2\u00a1\u00a2\7W\2\2\u00a2"+ - "\u00a5\7Z\2\2\u00a3\u00a4\7\64\2\2\u00a4\u00a6\7+\2\2\u00a5\u00a3\3\2"+ - "\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00a9\3\2\2\2\u00a7\u00aa\5@!\2\u00a8\u00aa"+ - "\5l\67\2\u00a9\u00a7\3\2\2\2\u00a9\u00a8\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa"+ - "\u00f2\3\2\2\2\u00ab\u00ac\7W\2\2\u00ac\u00af\7\24\2\2\u00ad\u00ae\7\64"+ - "\2\2\u00ae\u00b0\7+\2\2\u00af\u00ad\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0"+ - "\u00b1\3\2\2\2\u00b1\u00b4\t\5\2\2\u00b2\u00b5\5@!\2\u00b3\u00b5\5l\67"+ - "\2\u00b4\u00b2\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5\u00f2\3\2\2\2\u00b6\u00b9"+ - "\t\6\2\2\u00b7\u00b8\7\64\2\2\u00b8\u00ba\7+\2\2\u00b9\u00b7\3\2\2\2\u00b9"+ - "\u00ba\3\2\2\2\u00ba\u00bd\3\2\2\2\u00bb\u00be\5@!\2\u00bc\u00be\5l\67"+ - "\2\u00bd\u00bb\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be\u00f2\3\2\2\2\u00bf\u00c0"+ - "\7W\2\2\u00c0\u00c2\7-\2\2\u00c1\u00c3\5@!\2\u00c2\u00c1\3\2\2\2\u00c2"+ - "\u00c3\3\2\2\2\u00c3\u00f2\3\2\2\2\u00c4\u00c5\7W\2\2\u00c5\u00f2\7S\2"+ - "\2\u00c6\u00c7\7X\2\2\u00c7\u00ca\7Z\2\2\u00c8\u00c9\7\22\2\2\u00c9\u00cb"+ - "\5@!\2\u00ca\u00c8\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb\u00ce\3\2\2\2\u00cc"+ - "\u00cf\5@!\2\u00cd\u00cf\5l\67\2\u00ce\u00cc\3\2\2\2\u00ce\u00cd\3\2\2"+ - "\2\u00ce\u00cf\3\2\2\2\u00cf\u00d9\3\2\2\2\u00d0\u00d1\7`\2\2\u00d1\u00d6"+ - "\5t;\2\u00d2\u00d3\7\5\2\2\u00d3\u00d5\5t;\2\u00d4\u00d2\3\2\2\2\u00d5"+ - "\u00d8\3\2\2\2\u00d6\u00d4\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u00da\3\2"+ - "\2\2\u00d8\u00d6\3\2\2\2\u00d9\u00d0\3\2\2\2\u00d9\u00da\3\2\2\2\u00da"+ - "\u00f2\3\2\2\2\u00db\u00dc\7X\2\2\u00dc\u00df\7\24\2\2\u00dd\u00de\7\22"+ - "\2\2\u00de\u00e0\5t;\2\u00df\u00dd\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0\u00e4"+ - "\3\2\2\2\u00e1\u00e2\7Y\2\2\u00e2\u00e5\5@!\2\u00e3\u00e5\5l\67\2\u00e4"+ - "\u00e1\3\2\2\2\u00e4\u00e3\3\2\2\2\u00e4\u00e5\3\2\2\2\u00e5\u00e7\3\2"+ - "\2\2\u00e6\u00e8\5@!\2\u00e7\u00e6\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8\u00f2"+ - "\3\2\2\2\u00e9\u00ea\7X\2\2\u00ea\u00ef\7a\2\2\u00eb\u00ed\t\7\2\2\u00ec"+ - "\u00eb\3\2\2\2\u00ec\u00ed\3\2\2\2\u00ed\u00ee\3\2\2\2\u00ee\u00f0\5r"+ - ":\2\u00ef\u00ec\3\2\2\2\u00ef\u00f0\3\2\2\2\u00f0\u00f2\3\2\2\2\u00f1"+ - "\u0080\3\2\2\2\u00f1\u0081\3\2\2\2\u00f1\u0092\3\2\2\2\u00f1\u00a1\3\2"+ - "\2\2\u00f1\u00ab\3\2\2\2\u00f1\u00b6\3\2\2\2\u00f1\u00bf\3\2\2\2\u00f1"+ - "\u00c4\3\2\2\2\u00f1\u00c6\3\2\2\2\u00f1\u00db\3\2\2\2\u00f1\u00e9\3\2"+ - "\2\2\u00f2\7\3\2\2\2\u00f3\u00f4\7f\2\2\u00f4\u00f9\5\34\17\2\u00f5\u00f6"+ - "\7\5\2\2\u00f6\u00f8\5\34\17\2\u00f7\u00f5\3\2\2\2\u00f8\u00fb\3\2\2\2"+ - "\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2\u00fa\u00fd\3\2\2\2\u00fb\u00f9"+ - "\3\2\2\2\u00fc\u00f3\3\2\2\2\u00fc\u00fd\3\2\2\2\u00fd\u00fe\3\2\2\2\u00fe"+ - "\u00ff\5\n\6\2\u00ff\t\3\2\2\2\u0100\u010b\5\16\b\2\u0101\u0102\7J\2\2"+ - "\u0102\u0103\7\17\2\2\u0103\u0108\5\20\t\2\u0104\u0105\7\5\2\2\u0105\u0107"+ - "\5\20\t\2\u0106\u0104\3\2\2\2\u0107\u010a\3\2\2\2\u0108\u0106\3\2\2\2"+ - "\u0108\u0109\3\2\2\2\u0109\u010c\3\2\2\2\u010a\u0108\3\2\2\2\u010b\u0101"+ - "\3\2\2\2\u010b\u010c\3\2\2\2\u010c\u010e\3\2\2\2\u010d\u010f\5\f\7\2\u010e"+ - "\u010d\3\2\2\2\u010e\u010f\3\2\2\2\u010f\13\3\2\2\2\u0110\u0111\7<\2\2"+ - "\u0111\u0116\t\b\2\2\u0112\u0113\7k\2\2\u0113\u0114\t\b\2\2\u0114\u0116"+ - "\7q\2\2\u0115\u0110\3\2\2\2\u0115\u0112\3\2\2\2\u0116\r\3\2\2\2\u0117"+ - "\u011d\5\22\n\2\u0118\u0119\7\3\2\2\u0119\u011a\5\n\6\2\u011a\u011b\7"+ - "\4\2\2\u011b\u011d\3\2\2\2\u011c\u0117\3\2\2\2\u011c\u0118\3\2\2\2\u011d"+ - "\17\3\2\2\2\u011e\u0120\5\66\34\2\u011f\u0121\t\t\2\2\u0120\u011f\3\2"+ - "\2\2\u0120\u0121\3\2\2\2\u0121\u0124\3\2\2\2\u0122\u0123\7F\2\2\u0123"+ - "\u0125\t\n\2\2\u0124\u0122\3\2\2\2\u0124\u0125\3\2\2\2\u0125\21\3\2\2"+ - "\2\u0126\u0128\7V\2\2\u0127\u0129\5\36\20\2\u0128\u0127\3\2\2\2\u0128"+ - "\u0129\3\2\2\2\u0129\u012b\3\2\2\2\u012a\u012c\5 \21\2\u012b\u012a\3\2"+ - "\2\2\u012b\u012c\3\2\2\2\u012c\u012d\3\2\2\2\u012d\u012f\5\"\22\2\u012e"+ - "\u0130\5\24\13\2\u012f\u012e\3\2\2\2\u012f\u0130\3\2\2\2\u0130\u0133\3"+ - "\2\2\2\u0131\u0132\7e\2\2\u0132\u0134\58\35\2\u0133\u0131\3\2\2\2\u0133"+ - "\u0134\3\2\2\2\u0134\u0138\3\2\2\2\u0135\u0136\7/\2\2\u0136\u0137\7\17"+ - "\2\2\u0137\u0139\5\26\f\2\u0138\u0135\3\2\2\2\u0138\u0139\3\2\2\2\u0139"+ - "\u013c\3\2\2\2\u013a\u013b\7\60\2\2\u013b\u013d\58\35\2\u013c\u013a\3"+ - "\2\2\2\u013c\u013d\3\2\2\2\u013d\23\3\2\2\2\u013e\u013f\7*\2\2\u013f\u0144"+ - "\5&\24\2\u0140\u0141\7\5\2\2\u0141\u0143\5&\24\2\u0142\u0140\3\2\2\2\u0143"+ - "\u0146\3\2\2\2\u0144\u0142\3\2\2\2\u0144\u0145\3\2\2\2\u0145\u0148\3\2"+ - "\2\2\u0146\u0144\3\2\2\2\u0147\u0149\5\60\31\2\u0148\u0147\3\2\2\2\u0148"+ - "\u0149\3\2\2\2\u0149\25\3\2\2\2\u014a\u014c\5 \21\2\u014b\u014a\3\2\2"+ - "\2\u014b\u014c\3\2\2\2\u014c\u014d\3\2\2\2\u014d\u0152\5\30\r\2\u014e"+ - "\u014f\7\5\2\2\u014f\u0151\5\30\r\2\u0150\u014e\3\2\2\2\u0151\u0154\3"+ - "\2\2\2\u0152\u0150\3\2\2\2\u0152\u0153\3\2\2\2\u0153\27\3\2\2\2\u0154"+ - "\u0152\3\2\2\2\u0155\u0156\5\32\16\2\u0156\31\3\2\2\2\u0157\u0160\7\3"+ - "\2\2\u0158\u015d\5\66\34\2\u0159\u015a\7\5\2\2\u015a\u015c\5\66\34\2\u015b"+ - "\u0159\3\2\2\2\u015c\u015f\3\2\2\2\u015d\u015b\3\2\2\2\u015d\u015e\3\2"+ - "\2\2\u015e\u0161\3\2\2\2\u015f\u015d\3\2\2\2\u0160\u0158\3\2\2\2\u0160"+ - "\u0161\3\2\2\2\u0161\u0162\3\2\2\2\u0162\u0165\7\4\2\2\u0163\u0165\5\66"+ - "\34\2\u0164\u0157\3\2\2\2\u0164\u0163\3\2\2\2\u0165\33\3\2\2\2\u0166\u0167"+ - "\5j\66\2\u0167\u0168\7\f\2\2\u0168\u0169\7\3\2\2\u0169\u016a\5\n\6\2\u016a"+ - "\u016b\7\4\2\2\u016b\35\3\2\2\2\u016c\u016d\7_\2\2\u016d\u016e\7\u0082"+ - "\2\2\u016e\37\3\2\2\2\u016f\u0170\t\13\2\2\u0170!\3\2\2\2\u0171\u0176"+ - "\5$\23\2\u0172\u0173\7\5\2\2\u0173\u0175\5$\23\2\u0174\u0172\3\2\2\2\u0175"+ - "\u0178\3\2\2\2\u0176\u0174\3\2\2\2\u0176\u0177\3\2\2\2\u0177#\3\2\2\2"+ - "\u0178\u0176\3\2\2\2\u0179\u017e\5\66\34\2\u017a\u017c\7\f\2\2\u017b\u017a"+ - "\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\3\2\2\2\u017d\u017f\5j\66\2\u017e"+ - "\u017b\3\2\2\2\u017e\u017f\3\2\2\2\u017f%\3\2\2\2\u0180\u0184\5.\30\2"+ - "\u0181\u0183\5(\25\2\u0182\u0181\3\2\2\2\u0183\u0186\3\2\2\2\u0184\u0182"+ - "\3\2\2\2\u0184\u0185\3\2\2\2\u0185\'\3\2\2\2\u0186\u0184\3\2\2\2\u0187"+ - "\u0188\5*\26\2\u0188\u0189\78\2\2\u0189\u018b\5.\30\2\u018a\u018c\5,\27"+ - "\2\u018b\u018a\3\2\2\2\u018b\u018c\3\2\2\2\u018c\u0193\3\2\2\2\u018d\u018e"+ - "\7C\2\2\u018e\u018f\5*\26\2\u018f\u0190\78\2\2\u0190\u0191\5.\30\2\u0191"+ - "\u0193\3\2\2\2\u0192\u0187\3\2\2\2\u0192\u018d\3\2\2\2\u0193)\3\2\2\2"+ - "\u0194\u0196\7\65\2\2\u0195\u0194\3\2\2\2\u0195\u0196\3\2\2\2\u0196\u01a4"+ - "\3\2\2\2\u0197\u0199\7:\2\2\u0198\u019a\7K\2\2\u0199\u0198\3\2\2\2\u0199"+ - "\u019a\3\2\2\2\u019a\u01a4\3\2\2\2\u019b\u019d\7P\2\2\u019c\u019e\7K\2"+ - "\2\u019d\u019c\3\2\2\2\u019d\u019e\3\2\2\2\u019e\u01a4\3\2\2\2\u019f\u01a1"+ - "\7,\2\2\u01a0\u01a2\7K\2\2\u01a1\u01a0\3\2\2\2\u01a1\u01a2\3\2\2\2\u01a2"+ - "\u01a4\3\2\2\2\u01a3\u0195\3\2\2\2\u01a3\u0197\3\2\2\2\u01a3\u019b\3\2"+ - "\2\2\u01a3\u019f\3\2\2\2\u01a4+\3\2\2\2\u01a5\u01a6\7G\2\2\u01a6\u01b4"+ - "\58\35\2\u01a7\u01a8\7b\2\2\u01a8\u01a9\7\3\2\2\u01a9\u01ae\5j\66\2\u01aa"+ - "\u01ab\7\5\2\2\u01ab\u01ad\5j\66\2\u01ac\u01aa\3\2\2\2\u01ad\u01b0\3\2"+ - "\2\2\u01ae\u01ac\3\2\2\2\u01ae\u01af\3\2\2\2\u01af\u01b1\3\2\2\2\u01b0"+ - "\u01ae\3\2\2\2\u01b1\u01b2\7\4\2\2\u01b2\u01b4\3\2\2\2\u01b3\u01a5\3\2"+ - "\2\2\u01b3\u01a7\3\2\2\2\u01b4-\3\2\2\2\u01b5\u01b7\7+\2\2\u01b6\u01b5"+ - "\3\2\2\2\u01b6\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01bd\5l\67\2\u01b9"+ - "\u01bb\7\f\2\2\u01ba\u01b9\3\2\2\2\u01ba\u01bb\3\2\2\2\u01bb\u01bc\3\2"+ - "\2\2\u01bc\u01be\5h\65\2\u01bd\u01ba\3\2\2\2\u01bd\u01be\3\2\2\2\u01be"+ - "\u01d2\3\2\2\2\u01bf\u01c0\7\3\2\2\u01c0\u01c1\5\n\6\2\u01c1\u01c6\7\4"+ - "\2\2\u01c2\u01c4\7\f\2\2\u01c3\u01c2\3\2\2\2\u01c3\u01c4\3\2\2\2\u01c4"+ - "\u01c5\3\2\2\2\u01c5\u01c7\5h\65\2\u01c6\u01c3\3\2\2\2\u01c6\u01c7\3\2"+ - "\2\2\u01c7\u01d2\3\2\2\2\u01c8\u01c9\7\3\2\2\u01c9\u01ca\5&\24\2\u01ca"+ - "\u01cf\7\4\2\2\u01cb\u01cd\7\f\2\2\u01cc\u01cb\3\2\2\2\u01cc\u01cd\3\2"+ - "\2\2\u01cd\u01ce\3\2\2\2\u01ce\u01d0\5h\65\2\u01cf\u01cc\3\2\2\2\u01cf"+ - "\u01d0\3\2\2\2\u01d0\u01d2\3\2\2\2\u01d1\u01b6\3\2\2\2\u01d1\u01bf\3\2"+ - "\2\2\u01d1\u01c8\3\2\2\2\u01d2/\3\2\2\2\u01d3\u01d4\7N\2\2\u01d4\u01d5"+ - "\7\3\2\2\u01d5\u01d6\5\62\32\2\u01d6\u01d7\7(\2\2\u01d7\u01d8\5h\65\2"+ - "\u01d8\u01d9\7\63\2\2\u01d9\u01da\7\3\2\2\u01da\u01db\5\62\32\2\u01db"+ - "\u01dc\7\4\2\2\u01dc\u01dd\7\4\2\2\u01dd\61\3\2\2\2\u01de\u01e3\5\64\33"+ - "\2\u01df\u01e0\7\5\2\2\u01e0\u01e2\5\64\33\2\u01e1\u01df\3\2\2\2\u01e2"+ - "\u01e5\3\2\2\2\u01e3\u01e1\3\2\2\2\u01e3\u01e4\3\2\2\2\u01e4\63\3\2\2"+ - "\2\u01e5\u01e3\3\2\2\2\u01e6\u01eb\5F$\2\u01e7\u01e9\7\f\2\2\u01e8\u01e7"+ - "\3\2\2\2\u01e8\u01e9\3\2\2\2\u01e9\u01ea\3\2\2\2\u01ea\u01ec\5j\66\2\u01eb"+ - "\u01e8\3\2\2\2\u01eb\u01ec\3\2\2\2\u01ec\65\3\2\2\2\u01ed\u01ee\58\35"+ - "\2\u01ee\67\3\2\2\2\u01ef\u01f0\b\35\1\2\u01f0\u01f1\7D\2\2\u01f1\u020f"+ - "\58\35\n\u01f2\u01f3\7#\2\2\u01f3\u01f4\7\3\2\2\u01f4\u01f5\5\b\5\2\u01f5"+ - "\u01f6\7\4\2\2\u01f6\u020f\3\2\2\2\u01f7\u01f8\7R\2\2\u01f8\u01f9\7\3"+ - "\2\2\u01f9\u01fa\5t;\2\u01fa\u01fb\5:\36\2\u01fb\u01fc\7\4\2\2\u01fc\u020f"+ - "\3\2\2\2\u01fd\u01fe\7>\2\2\u01fe\u01ff\7\3\2\2\u01ff\u0200\5h\65\2\u0200"+ - "\u0201\7\5\2\2\u0201\u0202\5t;\2\u0202\u0203\5:\36\2\u0203\u0204\7\4\2"+ - "\2\u0204\u020f\3\2\2\2\u0205\u0206\7>\2\2\u0206\u0207\7\3\2\2\u0207\u0208"+ - "\5t;\2\u0208\u0209\7\5\2\2\u0209\u020a\5t;\2\u020a\u020b\5:\36\2\u020b"+ - "\u020c\7\4\2\2\u020c\u020f\3\2\2\2\u020d\u020f\5<\37\2\u020e\u01ef\3\2"+ - "\2\2\u020e\u01f2\3\2\2\2\u020e\u01f7\3\2\2\2\u020e\u01fd\3\2\2\2\u020e"+ - "\u0205\3\2\2\2\u020e\u020d\3\2\2\2\u020f\u0218\3\2\2\2\u0210\u0211\f\4"+ - "\2\2\u0211\u0212\7\n\2\2\u0212\u0217\58\35\5\u0213\u0214\f\3\2\2\u0214"+ - "\u0215\7I\2\2\u0215\u0217\58\35\4\u0216\u0210\3\2\2\2\u0216\u0213\3\2"+ - "\2\2\u0217\u021a\3\2\2\2\u0218\u0216\3\2\2\2\u0218\u0219\3\2\2\2\u0219"+ - "9\3\2\2\2\u021a\u0218\3\2\2\2\u021b\u021c\7\5\2\2\u021c\u021e\5t;\2\u021d"+ - "\u021b\3\2\2\2\u021e\u0221\3\2\2\2\u021f\u021d\3\2\2\2\u021f\u0220\3\2"+ - "\2\2\u0220;\3\2\2\2\u0221\u021f\3\2\2\2\u0222\u0224\5F$\2\u0223\u0225"+ - "\5> \2\u0224\u0223\3\2\2\2\u0224\u0225\3\2\2\2\u0225=\3\2\2\2\u0226\u0228"+ - "\7D\2\2\u0227\u0226\3\2\2\2\u0227\u0228\3\2\2\2\u0228\u0229\3\2\2\2\u0229"+ - "\u022a\7\16\2\2\u022a\u022b\5F$\2\u022b\u022c\7\n\2\2\u022c\u022d\5F$"+ - "\2\u022d\u0255\3\2\2\2\u022e\u0230\7D\2\2\u022f\u022e\3\2\2\2\u022f\u0230"+ - "\3\2\2\2\u0230\u0231\3\2\2\2\u0231\u0232\7\63\2\2\u0232\u0233\7\3\2\2"+ - "\u0233\u0238\5F$\2\u0234\u0235\7\5\2\2\u0235\u0237\5F$\2\u0236\u0234\3"+ - "\2\2\2\u0237\u023a\3\2\2\2\u0238\u0236\3\2\2\2\u0238\u0239\3\2\2\2\u0239"+ - "\u023b\3\2\2\2\u023a\u0238\3\2\2\2\u023b\u023c\7\4\2\2\u023c\u0255\3\2"+ - "\2\2\u023d\u023f\7D\2\2\u023e\u023d\3\2\2\2\u023e\u023f\3\2\2\2\u023f"+ - "\u0240\3\2\2\2\u0240\u0241\7\63\2\2\u0241\u0242\7\3\2\2\u0242\u0243\5"+ - "\b\5\2\u0243\u0244\7\4\2\2\u0244\u0255\3\2\2\2\u0245\u0247\7D\2\2\u0246"+ - "\u0245\3\2\2\2\u0246\u0247\3\2\2\2\u0247\u0248\3\2\2\2\u0248\u0249\7;"+ - "\2\2\u0249\u0255\5B\"\2\u024a\u024c\7D\2\2\u024b\u024a\3\2\2\2\u024b\u024c"+ - "\3\2\2\2\u024c\u024d\3\2\2\2\u024d\u024e\7Q\2\2\u024e\u0255\5t;\2\u024f"+ - "\u0251\7\67\2\2\u0250\u0252\7D\2\2\u0251\u0250\3\2\2\2\u0251\u0252\3\2"+ - "\2\2\u0252\u0253\3\2\2\2\u0253\u0255\7E\2\2\u0254\u0227\3\2\2\2\u0254"+ - "\u022f\3\2\2\2\u0254\u023e\3\2\2\2\u0254\u0246\3\2\2\2\u0254\u024b\3\2"+ - "\2\2\u0254\u024f\3\2\2\2\u0255?\3\2\2\2\u0256\u0257\7;\2\2\u0257\u0258"+ - "\5B\"\2\u0258A\3\2\2\2\u0259\u025b\5t;\2\u025a\u025c\5D#\2\u025b\u025a"+ - "\3\2\2\2\u025b\u025c\3\2\2\2\u025cC\3\2\2\2\u025d\u025e\7!\2\2\u025e\u0264"+ - "\5t;\2\u025f\u0260\7i\2\2\u0260\u0261\5t;\2\u0261\u0262\7q\2\2\u0262\u0264"+ - "\3\2\2\2\u0263\u025d\3\2\2\2\u0263\u025f\3\2\2\2\u0264E\3\2\2\2\u0265"+ - "\u0266\b$\1\2\u0266\u026a\5H%\2\u0267\u0268\t\7\2\2\u0268\u026a\5F$\6"+ - "\u0269\u0265\3\2\2\2\u0269\u0267\3\2\2\2\u026a\u0277\3\2\2\2\u026b\u026c"+ - "\f\5\2\2\u026c\u026d\t\f\2\2\u026d\u0276\5F$\6\u026e\u026f\f\4\2\2\u026f"+ - "\u0270\t\7\2\2\u0270\u0276\5F$\5\u0271\u0272\f\3\2\2\u0272\u0273\5^\60"+ - "\2\u0273\u0274\5F$\4\u0274\u0276\3\2\2\2\u0275\u026b\3\2\2\2\u0275\u026e"+ - "\3\2\2\2\u0275\u0271\3\2\2\2\u0276\u0279\3\2\2\2\u0277\u0275\3\2\2\2\u0277"+ - "\u0278\3\2\2\2\u0278G\3\2\2\2\u0279\u0277\3\2\2\2\u027a\u027b\b%\1\2\u027b"+ - "\u029f\5L\'\2\u027c\u029f\5R*\2\u027d\u029f\5J&\2\u027e\u029f\5\\/\2\u027f"+ - "\u0280\5h\65\2\u0280\u0281\7\177\2\2\u0281\u0283\3\2\2\2\u0282\u027f\3"+ - "\2\2\2\u0282\u0283\3\2\2\2\u0283\u0284\3\2\2\2\u0284\u029f\7{\2\2\u0285"+ - "\u029f\5V,\2\u0286\u0287\7\3\2\2\u0287\u0288\5\b\5\2\u0288\u0289\7\4\2"+ - "\2\u0289\u029f\3\2\2\2\u028a\u029f\5h\65\2\u028b\u028c\7\3\2\2\u028c\u028d"+ - "\5\66\34\2\u028d\u028e\7\4\2\2\u028e\u029f\3\2\2\2\u028f\u0291\7\20\2"+ - "\2\u0290\u0292\58\35\2\u0291\u0290\3\2\2\2\u0291\u0292\3\2\2\2\u0292\u0294"+ - "\3\2\2\2\u0293\u0295\5v<\2\u0294\u0293\3\2\2\2\u0295\u0296\3\2\2\2\u0296"+ - "\u0294\3\2\2\2\u0296\u0297\3\2\2\2\u0297\u029a\3\2\2\2\u0298\u0299\7\37"+ - "\2\2\u0299\u029b\58\35\2\u029a\u0298\3\2\2\2\u029a\u029b\3\2\2\2\u029b"+ - "\u029c\3\2\2\2\u029c\u029d\7 \2\2\u029d\u029f\3\2\2\2\u029e\u027a\3\2"+ - "\2\2\u029e\u027c\3\2\2\2\u029e\u027d\3\2\2\2\u029e\u027e\3\2\2\2\u029e"+ - "\u0282\3\2\2\2\u029e\u0285\3\2\2\2\u029e\u0286\3\2\2\2\u029e\u028a\3\2"+ - "\2\2\u029e\u028b\3\2\2\2\u029e\u028f\3\2\2\2\u029f\u02a5\3\2\2\2\u02a0"+ - "\u02a1\f\f\2\2\u02a1\u02a2\7~\2\2\u02a2\u02a4\5f\64\2\u02a3\u02a0\3\2"+ - "\2\2\u02a4\u02a7\3\2\2\2\u02a5\u02a3\3\2\2\2\u02a5\u02a6\3\2\2\2\u02a6"+ - "I\3\2\2\2\u02a7\u02a5\3\2\2\2\u02a8\u02ac\7\30\2\2\u02a9\u02ac\7\26\2"+ - "\2\u02aa\u02ac\7\27\2\2\u02ab\u02a8\3\2\2\2\u02ab\u02a9\3\2\2\2\u02ab"+ - "\u02aa\3\2\2\2\u02acK\3\2\2\2\u02ad\u02b8\5N(\2\u02ae\u02af\7j\2\2\u02af"+ - "\u02b0\5N(\2\u02b0\u02b1\7q\2\2\u02b1\u02b8\3\2\2\2\u02b2\u02b8\5P)\2"+ - "\u02b3\u02b4\7j\2\2\u02b4\u02b5\5P)\2\u02b5\u02b6\7q\2\2\u02b6\u02b8\3"+ - "\2\2\2\u02b7\u02ad\3\2\2\2\u02b7\u02ae\3\2\2\2\u02b7\u02b2\3\2\2\2\u02b7"+ - "\u02b3\3\2\2\2\u02b8M\3\2\2\2\u02b9\u02ba\7\21\2\2\u02ba\u02bb\7\3\2\2"+ - "\u02bb\u02bc\5\66\34\2\u02bc\u02bd\7\f\2\2\u02bd\u02be\5f\64\2\u02be\u02bf"+ - "\7\4\2\2\u02bfO\3\2\2\2\u02c0\u02c1\7\25\2\2\u02c1\u02c2\7\3\2\2\u02c2"+ - "\u02c3\5\66\34\2\u02c3\u02c4\7\5\2\2\u02c4\u02c5\5f\64\2\u02c5\u02c6\7"+ - "\4\2\2\u02c6Q\3\2\2\2\u02c7\u02cd\5T+\2\u02c8\u02c9\7j\2\2\u02c9\u02ca"+ - "\5T+\2\u02ca\u02cb\7q\2\2\u02cb\u02cd\3\2\2\2\u02cc\u02c7\3\2\2\2\u02cc"+ - "\u02c8\3\2\2\2\u02cdS\3\2\2\2\u02ce\u02cf\7%\2\2\u02cf\u02d0\7\3\2\2\u02d0"+ - "\u02d1\5j\66\2\u02d1\u02d2\7*\2\2\u02d2\u02d3\5F$\2\u02d3\u02d4\7\4\2"+ - "\2\u02d4U\3\2\2\2\u02d5\u02db\5X-\2\u02d6\u02d7\7j\2\2\u02d7\u02d8\5X"+ - "-\2\u02d8\u02d9\7q\2\2\u02d9\u02db\3\2\2\2\u02da\u02d5\3\2\2\2\u02da\u02d6"+ - "\3\2\2\2\u02dbW\3\2\2\2\u02dc\u02dd\5Z.\2\u02dd\u02e9\7\3\2\2\u02de\u02e0"+ - "\5 \21\2\u02df\u02de\3\2\2\2\u02df\u02e0\3\2\2\2\u02e0\u02e1\3\2\2\2\u02e1"+ - "\u02e6\5\66\34\2\u02e2\u02e3\7\5\2\2\u02e3\u02e5\5\66\34\2\u02e4\u02e2"+ - "\3\2\2\2\u02e5\u02e8\3\2\2\2\u02e6\u02e4\3\2\2\2\u02e6\u02e7\3\2\2\2\u02e7"+ - "\u02ea\3\2\2\2\u02e8\u02e6\3\2\2\2\u02e9\u02df\3\2\2\2\u02e9\u02ea\3\2"+ - "\2\2\u02ea\u02eb\3\2\2\2\u02eb\u02ec\7\4\2\2\u02ecY\3\2\2\2\u02ed\u02f1"+ - "\7:\2\2\u02ee\u02f1\7P\2\2\u02ef\u02f1\5j\66\2\u02f0\u02ed\3\2\2\2\u02f0"+ - "\u02ee\3\2\2\2\u02f0\u02ef\3\2\2\2\u02f1[\3\2\2\2\u02f2\u030d\7E\2\2\u02f3"+ - "\u030d\5b\62\2\u02f4\u030d\5r:\2\u02f5\u030d\5`\61\2\u02f6\u02f8\7\u0081"+ - "\2\2\u02f7\u02f6\3\2\2\2\u02f8\u02f9\3\2\2\2\u02f9\u02f7\3\2\2\2\u02f9"+ - "\u02fa\3\2\2\2\u02fa\u030d\3\2\2\2\u02fb\u030d\7\u0080\2\2\u02fc\u02fd"+ - "\7l\2\2\u02fd\u02fe\5t;\2\u02fe\u02ff\7q\2\2\u02ff\u030d\3\2\2\2\u0300"+ - "\u0301\7m\2\2\u0301\u0302\5t;\2\u0302\u0303\7q\2\2\u0303\u030d\3\2\2\2"+ - "\u0304\u0305\7n\2\2\u0305\u0306\5t;\2\u0306\u0307\7q\2\2\u0307\u030d\3"+ - "\2\2\2\u0308\u0309\7o\2\2\u0309\u030a\5t;\2\u030a\u030b\7q\2\2\u030b\u030d"+ - "\3\2\2\2\u030c\u02f2\3\2\2\2\u030c\u02f3\3\2\2\2\u030c\u02f4\3\2\2\2\u030c"+ - "\u02f5\3\2\2\2\u030c\u02f7\3\2\2\2\u030c\u02fb\3\2\2\2\u030c\u02fc\3\2"+ - "\2\2\u030c\u0300\3\2\2\2\u030c\u0304\3\2\2\2\u030c\u0308\3\2\2\2\u030d"+ - "]\3\2\2\2\u030e\u030f\t\r\2\2\u030f_\3\2\2\2\u0310\u0311\t\16\2\2\u0311"+ - "a\3\2\2\2\u0312\u0314\7\66\2\2\u0313\u0315\t\7\2\2\u0314\u0313\3\2\2\2"+ - "\u0314\u0315\3\2\2\2\u0315\u0318\3\2\2\2\u0316\u0319\5r:\2\u0317\u0319"+ - "\5t;\2\u0318\u0316\3\2\2\2\u0318\u0317\3\2\2\2\u0319\u031a\3\2\2\2\u031a"+ - "\u031d\5d\63\2\u031b\u031c\7^\2\2\u031c\u031e\5d\63\2\u031d\u031b\3\2"+ - "\2\2\u031d\u031e\3\2\2\2\u031ec\3\2\2\2\u031f\u0320\t\17\2\2\u0320e\3"+ - "\2\2\2\u0321\u0322\5j\66\2\u0322g\3\2\2\2\u0323\u0324\5j\66\2\u0324\u0325"+ - "\7\177\2\2\u0325\u0327\3\2\2\2\u0326\u0323\3\2\2\2\u0327\u032a\3\2\2\2"+ - "\u0328\u0326\3\2\2\2\u0328\u0329\3\2\2\2\u0329\u032b\3\2\2\2\u032a\u0328"+ - "\3\2\2\2\u032b\u032c\5j\66\2\u032ci\3\2\2\2\u032d\u0330\5n8\2\u032e\u0330"+ - "\5p9\2\u032f\u032d\3\2\2\2\u032f\u032e\3\2\2\2\u0330k\3\2\2\2\u0331\u0332"+ - "\5j\66\2\u0332\u0333\7\6\2\2\u0333\u0335\3\2\2\2\u0334\u0331\3\2\2\2\u0334"+ - "\u0335\3\2\2\2\u0335\u0336\3\2\2\2\u0336\u033e\7\u0086\2\2\u0337\u0338"+ - "\5j\66\2\u0338\u0339\7\6\2\2\u0339\u033b\3\2\2\2\u033a\u0337\3\2\2\2\u033a"+ - "\u033b\3\2\2\2\u033b\u033c\3\2\2\2\u033c\u033e\5j\66\2\u033d\u0334\3\2"+ - "\2\2\u033d\u033a\3\2\2\2\u033em\3\2\2\2\u033f\u0342\7\u0087\2\2\u0340"+ - "\u0342\7\u0088\2\2\u0341\u033f\3\2\2\2\u0341\u0340\3\2\2\2\u0342o\3\2"+ - "\2\2\u0343\u0347\7\u0084\2\2\u0344\u0347\5x=\2\u0345\u0347\7\u0085\2\2"+ - "\u0346\u0343\3\2\2\2\u0346\u0344\3\2\2\2\u0346\u0345\3\2\2\2\u0347q\3"+ - "\2\2\2\u0348\u034b\7\u0083\2\2\u0349\u034b\7\u0082\2\2\u034a\u0348\3\2"+ - "\2\2\u034a\u0349\3\2\2\2\u034bs\3\2\2\2\u034c\u034d\t\20\2\2\u034du\3"+ - "\2\2\2\u034e\u034f\7d\2\2\u034f\u0350\5\66\34\2\u0350\u0351\7\\\2\2\u0351"+ - "\u0352\5\66\34\2\u0352w\3\2\2\2\u0353\u0354\t\21\2\2\u0354y\3\2\2\2t\u0089"+ - "\u008b\u008f\u0098\u009a\u009e\u00a5\u00a9\u00af\u00b4\u00b9\u00bd\u00c2"+ - "\u00ca\u00ce\u00d6\u00d9\u00df\u00e4\u00e7\u00ec\u00ef\u00f1\u00f9\u00fc"+ - "\u0108\u010b\u010e\u0115\u011c\u0120\u0124\u0128\u012b\u012f\u0133\u0138"+ - "\u013c\u0144\u0148\u014b\u0152\u015d\u0160\u0164\u0176\u017b\u017e\u0184"+ - "\u018b\u0192\u0195\u0199\u019d\u01a1\u01a3\u01ae\u01b3\u01b6\u01ba\u01bd"+ - "\u01c3\u01c6\u01cc\u01cf\u01d1\u01e3\u01e8\u01eb\u020e\u0216\u0218\u021f"+ - "\u0224\u0227\u022f\u0238\u023e\u0246\u024b\u0251\u0254\u025b\u0263\u0269"+ - "\u0275\u0277\u0282\u0291\u0296\u029a\u029e\u02a5\u02ab\u02b7\u02cc\u02da"+ - "\u02df\u02e6\u02e9\u02f0\u02f9\u030c\u0314\u0318\u031d\u0328\u032f\u0334"+ - "\u033a\u033d\u0341\u0346\u034a"; + "\35\3\35\5\35\u0220\n\35\3\35\3\35\3\35\3\35\3\35\3\35\7\35\u0228\n\35"+ + "\f\35\16\35\u022b\13\35\3\36\3\36\7\36\u022f\n\36\f\36\16\36\u0232\13"+ + "\36\3\37\3\37\5\37\u0236\n\37\3 \5 \u0239\n \3 \3 \3 \3 \3 \3 \5 \u0241"+ + "\n \3 \3 \3 \3 \3 \7 \u0248\n \f \16 \u024b\13 \3 \3 \3 \5 \u0250\n \3"+ + " \3 \3 \3 \3 \3 \5 \u0258\n \3 \3 \3 \5 \u025d\n \3 \3 \3 \3 \5 \u0263"+ + "\n \3 \5 \u0266\n \3!\3!\3!\3\"\3\"\5\"\u026d\n\"\3#\3#\3#\3#\3#\3#\5"+ + "#\u0275\n#\3$\3$\3$\3$\5$\u027b\n$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\7$\u0287"+ + "\n$\f$\16$\u028a\13$\3%\3%\3%\3%\3%\3%\3%\3%\5%\u0294\n%\3%\3%\3%\3%\3"+ + "%\3%\3%\3%\3%\3%\3%\3%\3%\5%\u02a3\n%\3%\6%\u02a6\n%\r%\16%\u02a7\3%\3"+ + "%\5%\u02ac\n%\3%\3%\5%\u02b0\n%\3%\3%\3%\7%\u02b5\n%\f%\16%\u02b8\13%"+ + "\3&\3&\3&\5&\u02bd\n&\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\5\'\u02c9"+ + "\n\'\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\5*\u02de"+ + "\n*\3+\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\5,\u02ec\n,\3-\3-\3-\5-\u02f1"+ + "\n-\3-\3-\3-\7-\u02f6\n-\f-\16-\u02f9\13-\5-\u02fb\n-\3-\3-\3.\3.\3.\5"+ + ".\u0302\n.\3/\3/\3/\3/\3/\6/\u0309\n/\r/\16/\u030a\3/\3/\3/\3/\3/\3/\3"+ + "/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\5/\u031e\n/\3\60\3\60\3\61\3\61\3\62\3"+ + "\62\5\62\u0326\n\62\3\62\3\62\5\62\u032a\n\62\3\62\3\62\3\62\5\62\u032f"+ + "\n\62\3\63\3\63\3\64\3\64\3\65\3\65\3\65\7\65\u0338\n\65\f\65\16\65\u033b"+ + "\13\65\3\65\3\65\3\66\3\66\5\66\u0341\n\66\3\67\3\67\3\67\5\67\u0346\n"+ + "\67\3\67\3\67\3\67\3\67\5\67\u034c\n\67\3\67\5\67\u034f\n\67\38\38\58"+ + "\u0353\n8\39\39\39\59\u0358\n9\3:\3:\5:\u035c\n:\3;\3;\3<\3<\3<\3<\3<"+ + "\3=\3=\3=\2\58FH>\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62"+ + "\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvx\2\22\b\2\7\7\t\t\"\"==HHLL\4"+ + "\2..[[\4\2\t\tHH\4\2**\63\63\3\2\34\35\3\2yz\4\2\7\7\u0082\u0082\4\2\r"+ + "\r\34\34\4\2\'\'99\4\2\7\7\36\36\3\2{}\3\2rx\4\2&&]]\7\2\31\32\61\62?"+ + "BTUgh\3\2\u0080\u0081\31\2\b\t\23\24\26\31\33\33\"\"$$\'\')),.\61\61\66"+ + "\6699<=??AAHHLOQTWXZ[_accgg\2\u03cf\2z\3\2\2\2\4}\3\2\2\2\6\u0102\3\2"+ + "\2\2\b\u010d\3\2\2\2\n\u0111\3\2\2\2\f\u0126\3\2\2\2\16\u012d\3\2\2\2"+ + "\20\u012f\3\2\2\2\22\u0137\3\2\2\2\24\u014f\3\2\2\2\26\u015c\3\2\2\2\30"+ + "\u0166\3\2\2\2\32\u0175\3\2\2\2\34\u0177\3\2\2\2\36\u017d\3\2\2\2 \u0180"+ + "\3\2\2\2\"\u0182\3\2\2\2$\u018a\3\2\2\2&\u0191\3\2\2\2(\u01a3\3\2\2\2"+ + "*\u01b4\3\2\2\2,\u01c4\3\2\2\2.\u01e2\3\2\2\2\60\u01e4\3\2\2\2\62\u01ef"+ + "\3\2\2\2\64\u01f7\3\2\2\2\66\u01fe\3\2\2\28\u021f\3\2\2\2:\u0230\3\2\2"+ + "\2<\u0233\3\2\2\2>\u0265\3\2\2\2@\u0267\3\2\2\2B\u026a\3\2\2\2D\u0274"+ + "\3\2\2\2F\u027a\3\2\2\2H\u02af\3\2\2\2J\u02bc\3\2\2\2L\u02c8\3\2\2\2N"+ + "\u02ca\3\2\2\2P\u02d1\3\2\2\2R\u02dd\3\2\2\2T\u02df\3\2\2\2V\u02eb\3\2"+ + "\2\2X\u02ed\3\2\2\2Z\u0301\3\2\2\2\\\u031d\3\2\2\2^\u031f\3\2\2\2`\u0321"+ + "\3\2\2\2b\u0323\3\2\2\2d\u0330\3\2\2\2f\u0332\3\2\2\2h\u0339\3\2\2\2j"+ + "\u0340\3\2\2\2l\u034e\3\2\2\2n\u0352\3\2\2\2p\u0357\3\2\2\2r\u035b\3\2"+ + "\2\2t\u035d\3\2\2\2v\u035f\3\2\2\2x\u0364\3\2\2\2z{\5\6\4\2{|\7\2\2\3"+ + "|\3\3\2\2\2}~\5\66\34\2~\177\7\2\2\3\177\5\3\2\2\2\u0080\u0103\5\b\5\2"+ + "\u0081\u008f\7$\2\2\u0082\u008b\7\3\2\2\u0083\u0084\7O\2\2\u0084\u008a"+ + "\t\2\2\2\u0085\u0086\7)\2\2\u0086\u008a\t\3\2\2\u0087\u0088\7c\2\2\u0088"+ + "\u008a\5`\61\2\u0089\u0083\3\2\2\2\u0089\u0085\3\2\2\2\u0089\u0087\3\2"+ + "\2\2\u008a\u008d\3\2\2\2\u008b\u0089\3\2\2\2\u008b\u008c\3\2\2\2\u008c"+ + "\u008e\3\2\2\2\u008d\u008b\3\2\2\2\u008e\u0090\7\4\2\2\u008f\u0082\3\2"+ + "\2\2\u008f\u0090\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u0103\5\6\4\2\u0092"+ + "\u009e\7\33\2\2\u0093\u009a\7\3\2\2\u0094\u0095\7O\2\2\u0095\u0099\t\4"+ + "\2\2\u0096\u0097\7)\2\2\u0097\u0099\t\3\2\2\u0098\u0094\3\2\2\2\u0098"+ + "\u0096\3\2\2\2\u0099\u009c\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2"+ + "\2\2\u009b\u009d\3\2\2\2\u009c\u009a\3\2\2\2\u009d\u009f\7\4\2\2\u009e"+ + "\u0093\3\2\2\2\u009e\u009f\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u0103\5\6"+ + "\4\2\u00a1\u00a2\7W\2\2\u00a2\u00a8\7Z\2\2\u00a3\u00a6\7\22\2\2\u00a4"+ + "\u00a7\5@!\2\u00a5\u00a7\5t;\2\u00a6\u00a4\3\2\2\2\u00a6\u00a5\3\2\2\2"+ + "\u00a7\u00a9\3\2\2\2\u00a8\u00a3\3\2\2\2\u00a8\u00a9\3\2\2\2\u00a9\u00ac"+ + "\3\2\2\2\u00aa\u00ab\7\64\2\2\u00ab\u00ad\7+\2\2\u00ac\u00aa\3\2\2\2\u00ac"+ + "\u00ad\3\2\2\2\u00ad\u00b0\3\2\2\2\u00ae\u00b1\5@!\2\u00af\u00b1\5l\67"+ + "\2\u00b0\u00ae\3\2\2\2\u00b0\u00af\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u0103"+ + "\3\2\2\2\u00b2\u00b3\7W\2\2\u00b3\u00b6\7\24\2\2\u00b4\u00b5\7\22\2\2"+ + "\u00b5\u00b7\5t;\2\u00b6\u00b4\3\2\2\2\u00b6\u00b7\3\2\2\2\u00b7\u00ba"+ + "\3\2\2\2\u00b8\u00b9\7\64\2\2\u00b9\u00bb\7+\2\2\u00ba\u00b8\3\2\2\2\u00ba"+ + "\u00bb\3\2\2\2\u00bb\u00bc\3\2\2\2\u00bc\u00bf\t\5\2\2\u00bd\u00c0\5@"+ + "!\2\u00be\u00c0\5l\67\2\u00bf\u00bd\3\2\2\2\u00bf\u00be\3\2\2\2\u00c0"+ + "\u0103\3\2\2\2\u00c1\u00c4\t\6\2\2\u00c2\u00c3\7\22\2\2\u00c3\u00c5\5"+ + "t;\2\u00c4\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c8\3\2\2\2\u00c6"+ + "\u00c7\7\64\2\2\u00c7\u00c9\7+\2\2\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2"+ + "\2\2\u00c9\u00cc\3\2\2\2\u00ca\u00cd\5@!\2\u00cb\u00cd\5l\67\2\u00cc\u00ca"+ + "\3\2\2\2\u00cc\u00cb\3\2\2\2\u00cd\u0103\3\2\2\2\u00ce\u00cf\7W\2\2\u00cf"+ + "\u00d1\7-\2\2\u00d0\u00d2\5@!\2\u00d1\u00d0\3\2\2\2\u00d1\u00d2\3\2\2"+ + "\2\u00d2\u0103\3\2\2\2\u00d3\u00d4\7W\2\2\u00d4\u0103\7S\2\2\u00d5\u00d6"+ + "\7W\2\2\u00d6\u0103\7\23\2\2\u00d7\u00d8\7X\2\2\u00d8\u00db\7Z\2\2\u00d9"+ + "\u00da\7\22\2\2\u00da\u00dc\5@!\2\u00db\u00d9\3\2\2\2\u00db\u00dc\3\2"+ + "\2\2\u00dc\u00df\3\2\2\2\u00dd\u00e0\5@!\2\u00de\u00e0\5l\67\2\u00df\u00dd"+ + "\3\2\2\2\u00df\u00de\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0\u00ea\3\2\2\2\u00e1"+ + "\u00e2\7`\2\2\u00e2\u00e7\5t;\2\u00e3\u00e4\7\5\2\2\u00e4\u00e6\5t;\2"+ + "\u00e5\u00e3\3\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8"+ + "\3\2\2\2\u00e8\u00eb\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00e1\3\2\2\2\u00ea"+ + "\u00eb\3\2\2\2\u00eb\u0103\3\2\2\2\u00ec\u00ed\7X\2\2\u00ed\u00f0\7\24"+ + "\2\2\u00ee\u00ef\7\22\2\2\u00ef\u00f1\5t;\2\u00f0\u00ee\3\2\2\2\u00f0"+ + "\u00f1\3\2\2\2\u00f1\u00f5\3\2\2\2\u00f2\u00f3\7Y\2\2\u00f3\u00f6\5@!"+ + "\2\u00f4\u00f6\5l\67\2\u00f5\u00f2\3\2\2\2\u00f5\u00f4\3\2\2\2\u00f5\u00f6"+ + "\3\2\2\2\u00f6\u00f8\3\2\2\2\u00f7\u00f9\5@!\2\u00f8\u00f7\3\2\2\2\u00f8"+ + "\u00f9\3\2\2\2\u00f9\u0103\3\2\2\2\u00fa\u00fb\7X\2\2\u00fb\u0100\7a\2"+ + "\2\u00fc\u00fe\t\7\2\2\u00fd\u00fc\3\2\2\2\u00fd\u00fe\3\2\2\2\u00fe\u00ff"+ + "\3\2\2\2\u00ff\u0101\5r:\2\u0100\u00fd\3\2\2\2\u0100\u0101\3\2\2\2\u0101"+ + "\u0103\3\2\2\2\u0102\u0080\3\2\2\2\u0102\u0081\3\2\2\2\u0102\u0092\3\2"+ + "\2\2\u0102\u00a1\3\2\2\2\u0102\u00b2\3\2\2\2\u0102\u00c1\3\2\2\2\u0102"+ + "\u00ce\3\2\2\2\u0102\u00d3\3\2\2\2\u0102\u00d5\3\2\2\2\u0102\u00d7\3\2"+ + "\2\2\u0102\u00ec\3\2\2\2\u0102\u00fa\3\2\2\2\u0103\7\3\2\2\2\u0104\u0105"+ + "\7f\2\2\u0105\u010a\5\34\17\2\u0106\u0107\7\5\2\2\u0107\u0109\5\34\17"+ + "\2\u0108\u0106\3\2\2\2\u0109\u010c\3\2\2\2\u010a\u0108\3\2\2\2\u010a\u010b"+ + "\3\2\2\2\u010b\u010e\3\2\2\2\u010c\u010a\3\2\2\2\u010d\u0104\3\2\2\2\u010d"+ + "\u010e\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u0110\5\n\6\2\u0110\t\3\2\2\2"+ + "\u0111\u011c\5\16\b\2\u0112\u0113\7J\2\2\u0113\u0114\7\17\2\2\u0114\u0119"+ + "\5\20\t\2\u0115\u0116\7\5\2\2\u0116\u0118\5\20\t\2\u0117\u0115\3\2\2\2"+ + "\u0118\u011b\3\2\2\2\u0119\u0117\3\2\2\2\u0119\u011a\3\2\2\2\u011a\u011d"+ + "\3\2\2\2\u011b\u0119\3\2\2\2\u011c\u0112\3\2\2\2\u011c\u011d\3\2\2\2\u011d"+ + "\u011f\3\2\2\2\u011e\u0120\5\f\7\2\u011f\u011e\3\2\2\2\u011f\u0120\3\2"+ + "\2\2\u0120\13\3\2\2\2\u0121\u0122\7<\2\2\u0122\u0127\t\b\2\2\u0123\u0124"+ + "\7k\2\2\u0124\u0125\t\b\2\2\u0125\u0127\7q\2\2\u0126\u0121\3\2\2\2\u0126"+ + "\u0123\3\2\2\2\u0127\r\3\2\2\2\u0128\u012e\5\22\n\2\u0129\u012a\7\3\2"+ + "\2\u012a\u012b\5\n\6\2\u012b\u012c\7\4\2\2\u012c\u012e\3\2\2\2\u012d\u0128"+ + "\3\2\2\2\u012d\u0129\3\2\2\2\u012e\17\3\2\2\2\u012f\u0131\5\66\34\2\u0130"+ + "\u0132\t\t\2\2\u0131\u0130\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2"+ + "\2\2\u0133\u0134\7F\2\2\u0134\u0136\t\n\2\2\u0135\u0133\3\2\2\2\u0135"+ + "\u0136\3\2\2\2\u0136\21\3\2\2\2\u0137\u0139\7V\2\2\u0138\u013a\5\36\20"+ + "\2\u0139\u0138\3\2\2\2\u0139\u013a\3\2\2\2\u013a\u013c\3\2\2\2\u013b\u013d"+ + "\5 \21\2\u013c\u013b\3\2\2\2\u013c\u013d\3\2\2\2\u013d\u013e\3\2\2\2\u013e"+ + "\u0140\5\"\22\2\u013f\u0141\5\24\13\2\u0140\u013f\3\2\2\2\u0140\u0141"+ + "\3\2\2\2\u0141\u0144\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0145\58\35\2\u0144"+ + "\u0142\3\2\2\2\u0144\u0145\3\2\2\2\u0145\u0149\3\2\2\2\u0146\u0147\7/"+ + "\2\2\u0147\u0148\7\17\2\2\u0148\u014a\5\26\f\2\u0149\u0146\3\2\2\2\u0149"+ + "\u014a\3\2\2\2\u014a\u014d\3\2\2\2\u014b\u014c\7\60\2\2\u014c\u014e\5"+ + "8\35\2\u014d\u014b\3\2\2\2\u014d\u014e\3\2\2\2\u014e\23\3\2\2\2\u014f"+ + "\u0150\7*\2\2\u0150\u0155\5&\24\2\u0151\u0152\7\5\2\2\u0152\u0154\5&\24"+ + "\2\u0153\u0151\3\2\2\2\u0154\u0157\3\2\2\2\u0155\u0153\3\2\2\2\u0155\u0156"+ + "\3\2\2\2\u0156\u0159\3\2\2\2\u0157\u0155\3\2\2\2\u0158\u015a\5\60\31\2"+ + "\u0159\u0158\3\2\2\2\u0159\u015a\3\2\2\2\u015a\25\3\2\2\2\u015b\u015d"+ + "\5 \21\2\u015c\u015b\3\2\2\2\u015c\u015d\3\2\2\2\u015d\u015e\3\2\2\2\u015e"+ + "\u0163\5\30\r\2\u015f\u0160\7\5\2\2\u0160\u0162\5\30\r\2\u0161\u015f\3"+ + "\2\2\2\u0162\u0165\3\2\2\2\u0163\u0161\3\2\2\2\u0163\u0164\3\2\2\2\u0164"+ + "\27\3\2\2\2\u0165\u0163\3\2\2\2\u0166\u0167\5\32\16\2\u0167\31\3\2\2\2"+ + "\u0168\u0171\7\3\2\2\u0169\u016e\5\66\34\2\u016a\u016b\7\5\2\2\u016b\u016d"+ + "\5\66\34\2\u016c\u016a\3\2\2\2\u016d\u0170\3\2\2\2\u016e\u016c\3\2\2\2"+ + "\u016e\u016f\3\2\2\2\u016f\u0172\3\2\2\2\u0170\u016e\3\2\2\2\u0171\u0169"+ + "\3\2\2\2\u0171\u0172\3\2\2\2\u0172\u0173\3\2\2\2\u0173\u0176\7\4\2\2\u0174"+ + "\u0176\5\66\34\2\u0175\u0168\3\2\2\2\u0175\u0174\3\2\2\2\u0176\33\3\2"+ + "\2\2\u0177\u0178\5j\66\2\u0178\u0179\7\f\2\2\u0179\u017a\7\3\2\2\u017a"+ + "\u017b\5\n\6\2\u017b\u017c\7\4\2\2\u017c\35\3\2\2\2\u017d\u017e\7_\2\2"+ + "\u017e\u017f\7\u0082\2\2\u017f\37\3\2\2\2\u0180\u0181\t\13\2\2\u0181!"+ + "\3\2\2\2\u0182\u0187\5$\23\2\u0183\u0184\7\5\2\2\u0184\u0186\5$\23\2\u0185"+ + "\u0183\3\2\2\2\u0186\u0189\3\2\2\2\u0187\u0185\3\2\2\2\u0187\u0188\3\2"+ + "\2\2\u0188#\3\2\2\2\u0189\u0187\3\2\2\2\u018a\u018f\5\66\34\2\u018b\u018d"+ + "\7\f\2\2\u018c\u018b\3\2\2\2\u018c\u018d\3\2\2\2\u018d\u018e\3\2\2\2\u018e"+ + "\u0190\5j\66\2\u018f\u018c\3\2\2\2\u018f\u0190\3\2\2\2\u0190%\3\2\2\2"+ + "\u0191\u0195\5.\30\2\u0192\u0194\5(\25\2\u0193\u0192\3\2\2\2\u0194\u0197"+ + "\3\2\2\2\u0195\u0193\3\2\2\2\u0195\u0196\3\2\2\2\u0196\'\3\2\2\2\u0197"+ + "\u0195\3\2\2\2\u0198\u0199\5*\26\2\u0199\u019a\78\2\2\u019a\u019c\5.\30"+ + "\2\u019b\u019d\5,\27\2\u019c\u019b\3\2\2\2\u019c\u019d\3\2\2\2\u019d\u01a4"+ + "\3\2\2\2\u019e\u019f\7C\2\2\u019f\u01a0\5*\26\2\u01a0\u01a1\78\2\2\u01a1"+ + "\u01a2\5.\30\2\u01a2\u01a4\3\2\2\2\u01a3\u0198\3\2\2\2\u01a3\u019e\3\2"+ + "\2\2\u01a4)\3\2\2\2\u01a5\u01a7\7\65\2\2\u01a6\u01a5\3\2\2\2\u01a6\u01a7"+ + "\3\2\2\2\u01a7\u01b5\3\2\2\2\u01a8\u01aa\7:\2\2\u01a9\u01ab\7K\2\2\u01aa"+ + "\u01a9\3\2\2\2\u01aa\u01ab\3\2\2\2\u01ab\u01b5\3\2\2\2\u01ac\u01ae\7P"+ + "\2\2\u01ad\u01af\7K\2\2\u01ae\u01ad\3\2\2\2\u01ae\u01af\3\2\2\2\u01af"+ + "\u01b5\3\2\2\2\u01b0\u01b2\7,\2\2\u01b1\u01b3\7K\2\2\u01b2\u01b1\3\2\2"+ + "\2\u01b2\u01b3\3\2\2\2\u01b3\u01b5\3\2\2\2\u01b4\u01a6\3\2\2\2\u01b4\u01a8"+ + "\3\2\2\2\u01b4\u01ac\3\2\2\2\u01b4\u01b0\3\2\2\2\u01b5+\3\2\2\2\u01b6"+ + "\u01b7\7G\2\2\u01b7\u01c5\58\35\2\u01b8\u01b9\7b\2\2\u01b9\u01ba\7\3\2"+ + "\2\u01ba\u01bf\5j\66\2\u01bb\u01bc\7\5\2\2\u01bc\u01be\5j\66\2\u01bd\u01bb"+ + "\3\2\2\2\u01be\u01c1\3\2\2\2\u01bf\u01bd\3\2\2\2\u01bf\u01c0\3\2\2\2\u01c0"+ + "\u01c2\3\2\2\2\u01c1\u01bf\3\2\2\2\u01c2\u01c3\7\4\2\2\u01c3\u01c5\3\2"+ + "\2\2\u01c4\u01b6\3\2\2\2\u01c4\u01b8\3\2\2\2\u01c5-\3\2\2\2\u01c6\u01c8"+ + "\7+\2\2\u01c7\u01c6\3\2\2\2\u01c7\u01c8\3\2\2\2\u01c8\u01c9\3\2\2\2\u01c9"+ + "\u01ce\5l\67\2\u01ca\u01cc\7\f\2\2\u01cb\u01ca\3\2\2\2\u01cb\u01cc\3\2"+ + "\2\2\u01cc\u01cd\3\2\2\2\u01cd\u01cf\5h\65\2\u01ce\u01cb\3\2\2\2\u01ce"+ + "\u01cf\3\2\2\2\u01cf\u01e3\3\2\2\2\u01d0\u01d1\7\3\2\2\u01d1\u01d2\5\n"+ + "\6\2\u01d2\u01d7\7\4\2\2\u01d3\u01d5\7\f\2\2\u01d4\u01d3\3\2\2\2\u01d4"+ + "\u01d5\3\2\2\2\u01d5\u01d6\3\2\2\2\u01d6\u01d8\5h\65\2\u01d7\u01d4\3\2"+ + "\2\2\u01d7\u01d8\3\2\2\2\u01d8\u01e3\3\2\2\2\u01d9\u01da\7\3\2\2\u01da"+ + "\u01db\5&\24\2\u01db\u01e0\7\4\2\2\u01dc\u01de\7\f\2\2\u01dd\u01dc\3\2"+ + "\2\2\u01dd\u01de\3\2\2\2\u01de\u01df\3\2\2\2\u01df\u01e1\5h\65\2\u01e0"+ + "\u01dd\3\2\2\2\u01e0\u01e1\3\2\2\2\u01e1\u01e3\3\2\2\2\u01e2\u01c7\3\2"+ + "\2\2\u01e2\u01d0\3\2\2\2\u01e2\u01d9\3\2\2\2\u01e3/\3\2\2\2\u01e4\u01e5"+ + "\7N\2\2\u01e5\u01e6\7\3\2\2\u01e6\u01e7\5\62\32\2\u01e7\u01e8\7(\2\2\u01e8"+ + "\u01e9\5h\65\2\u01e9\u01ea\7\63\2\2\u01ea\u01eb\7\3\2\2\u01eb\u01ec\5"+ + "\62\32\2\u01ec\u01ed\7\4\2\2\u01ed\u01ee\7\4\2\2\u01ee\61\3\2\2\2\u01ef"+ + "\u01f4\5\64\33\2\u01f0\u01f1\7\5\2\2\u01f1\u01f3\5\64\33\2\u01f2\u01f0"+ + "\3\2\2\2\u01f3\u01f6\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f4\u01f5\3\2\2\2\u01f5"+ + "\63\3\2\2\2\u01f6\u01f4\3\2\2\2\u01f7\u01fc\5F$\2\u01f8\u01fa\7\f\2\2"+ + "\u01f9\u01f8\3\2\2\2\u01f9\u01fa\3\2\2\2\u01fa\u01fb\3\2\2\2\u01fb\u01fd"+ + "\5j\66\2\u01fc\u01f9\3\2\2\2\u01fc\u01fd\3\2\2\2\u01fd\65\3\2\2\2\u01fe"+ + "\u01ff\58\35\2\u01ff\67\3\2\2\2\u0200\u0201\b\35\1\2\u0201\u0202\7D\2"+ + "\2\u0202\u0220\58\35\n\u0203\u0204\7#\2\2\u0204\u0205\7\3\2\2\u0205\u0206"+ + "\5\b\5\2\u0206\u0207\7\4\2\2\u0207\u0220\3\2\2\2\u0208\u0209\7R\2\2\u0209"+ + "\u020a\7\3\2\2\u020a\u020b\5t;\2\u020b\u020c\5:\36\2\u020c\u020d\7\4\2"+ + "\2\u020d\u0220\3\2\2\2\u020e\u020f\7>\2\2\u020f\u0210\7\3\2\2\u0210\u0211"+ + "\5h\65\2\u0211\u0212\7\5\2\2\u0212\u0213\5t;\2\u0213\u0214\5:\36\2\u0214"+ + "\u0215\7\4\2\2\u0215\u0220\3\2\2\2\u0216\u0217\7>\2\2\u0217\u0218\7\3"+ + "\2\2\u0218\u0219\5t;\2\u0219\u021a\7\5\2\2\u021a\u021b\5t;\2\u021b\u021c"+ + "\5:\36\2\u021c\u021d\7\4\2\2\u021d\u0220\3\2\2\2\u021e\u0220\5<\37\2\u021f"+ + "\u0200\3\2\2\2\u021f\u0203\3\2\2\2\u021f\u0208\3\2\2\2\u021f\u020e\3\2"+ + "\2\2\u021f\u0216\3\2\2\2\u021f\u021e\3\2\2\2\u0220\u0229\3\2\2\2\u0221"+ + "\u0222\f\4\2\2\u0222\u0223\7\n\2\2\u0223\u0228\58\35\5\u0224\u0225\f\3"+ + "\2\2\u0225\u0226\7I\2\2\u0226\u0228\58\35\4\u0227\u0221\3\2\2\2\u0227"+ + "\u0224\3\2\2\2\u0228\u022b\3\2\2\2\u0229\u0227\3\2\2\2\u0229\u022a\3\2"+ + "\2\2\u022a9\3\2\2\2\u022b\u0229\3\2\2\2\u022c\u022d\7\5\2\2\u022d\u022f"+ + "\5t;\2\u022e\u022c\3\2\2\2\u022f\u0232\3\2\2\2\u0230\u022e\3\2\2\2\u0230"+ + "\u0231\3\2\2\2\u0231;\3\2\2\2\u0232\u0230\3\2\2\2\u0233\u0235\5F$\2\u0234"+ + "\u0236\5> \2\u0235\u0234\3\2\2\2\u0235\u0236\3\2\2\2\u0236=\3\2\2\2\u0237"+ + "\u0239\7D\2\2\u0238\u0237\3\2\2\2\u0238\u0239\3\2\2\2\u0239\u023a\3\2"+ + "\2\2\u023a\u023b\7\16\2\2\u023b\u023c\5F$\2\u023c\u023d\7\n\2\2\u023d"+ + "\u023e\5F$\2\u023e\u0266\3\2\2\2\u023f\u0241\7D\2\2\u0240\u023f\3\2\2"+ + "\2\u0240\u0241\3\2\2\2\u0241\u0242\3\2\2\2\u0242\u0243\7\63\2\2\u0243"+ + "\u0244\7\3\2\2\u0244\u0249\5F$\2\u0245\u0246\7\5\2\2\u0246\u0248\5F$\2"+ + "\u0247\u0245\3\2\2\2\u0248\u024b\3\2\2\2\u0249\u0247\3\2\2\2\u0249\u024a"+ + "\3\2\2\2\u024a\u024c\3\2\2\2\u024b\u0249\3\2\2\2\u024c\u024d\7\4\2\2\u024d"+ + "\u0266\3\2\2\2\u024e\u0250\7D\2\2\u024f\u024e\3\2\2\2\u024f\u0250\3\2"+ + "\2\2\u0250\u0251\3\2\2\2\u0251\u0252\7\63\2\2\u0252\u0253\7\3\2\2\u0253"+ + "\u0254\5\b\5\2\u0254\u0255\7\4\2\2\u0255\u0266\3\2\2\2\u0256\u0258\7D"+ + "\2\2\u0257\u0256\3\2\2\2\u0257\u0258\3\2\2\2\u0258\u0259\3\2\2\2\u0259"+ + "\u025a\7;\2\2\u025a\u0266\5B\"\2\u025b\u025d\7D\2\2\u025c\u025b\3\2\2"+ + "\2\u025c\u025d\3\2\2\2\u025d\u025e\3\2\2\2\u025e\u025f\7Q\2\2\u025f\u0266"+ + "\5t;\2\u0260\u0262\7\67\2\2\u0261\u0263\7D\2\2\u0262\u0261\3\2\2\2\u0262"+ + "\u0263\3\2\2\2\u0263\u0264\3\2\2\2\u0264\u0266\7E\2\2\u0265\u0238\3\2"+ + "\2\2\u0265\u0240\3\2\2\2\u0265\u024f\3\2\2\2\u0265\u0257\3\2\2\2\u0265"+ + "\u025c\3\2\2\2\u0265\u0260\3\2\2\2\u0266?\3\2\2\2\u0267\u0268\7;\2\2\u0268"+ + "\u0269\5B\"\2\u0269A\3\2\2\2\u026a\u026c\5t;\2\u026b\u026d\5D#\2\u026c"+ + "\u026b\3\2\2\2\u026c\u026d\3\2\2\2\u026dC\3\2\2\2\u026e\u026f\7!\2\2\u026f"+ + "\u0275\5t;\2\u0270\u0271\7i\2\2\u0271\u0272\5t;\2\u0272\u0273\7q\2\2\u0273"+ + "\u0275\3\2\2\2\u0274\u026e\3\2\2\2\u0274\u0270\3\2\2\2\u0275E\3\2\2\2"+ + "\u0276\u0277\b$\1\2\u0277\u027b\5H%\2\u0278\u0279\t\7\2\2\u0279\u027b"+ + "\5F$\6\u027a\u0276\3\2\2\2\u027a\u0278\3\2\2\2\u027b\u0288\3\2\2\2\u027c"+ + "\u027d\f\5\2\2\u027d\u027e\t\f\2\2\u027e\u0287\5F$\6\u027f\u0280\f\4\2"+ + "\2\u0280\u0281\t\7\2\2\u0281\u0287\5F$\5\u0282\u0283\f\3\2\2\u0283\u0284"+ + "\5^\60\2\u0284\u0285\5F$\4\u0285\u0287\3\2\2\2\u0286\u027c\3\2\2\2\u0286"+ + "\u027f\3\2\2\2\u0286\u0282\3\2\2\2\u0287\u028a\3\2\2\2\u0288\u0286\3\2"+ + "\2\2\u0288\u0289\3\2\2\2\u0289G\3\2\2\2\u028a\u0288\3\2\2\2\u028b\u028c"+ + "\b%\1\2\u028c\u02b0\5L\'\2\u028d\u02b0\5R*\2\u028e\u02b0\5J&\2\u028f\u02b0"+ + "\5\\/\2\u0290\u0291\5h\65\2\u0291\u0292\7\177\2\2\u0292\u0294\3\2\2\2"+ + "\u0293\u0290\3\2\2\2\u0293\u0294\3\2\2\2\u0294\u0295\3\2\2\2\u0295\u02b0"+ + "\7{\2\2\u0296\u02b0\5V,\2\u0297\u0298\7\3\2\2\u0298\u0299\5\b\5\2\u0299"+ + "\u029a\7\4\2\2\u029a\u02b0\3\2\2\2\u029b\u02b0\5h\65\2\u029c\u029d\7\3"+ + "\2\2\u029d\u029e\5\66\34\2\u029e\u029f\7\4\2\2\u029f\u02b0\3\2\2\2\u02a0"+ + "\u02a2\7\20\2\2\u02a1\u02a3\58\35\2\u02a2\u02a1\3\2\2\2\u02a2\u02a3\3"+ + "\2\2\2\u02a3\u02a5\3\2\2\2\u02a4\u02a6\5v<\2\u02a5\u02a4\3\2\2\2\u02a6"+ + "\u02a7\3\2\2\2\u02a7\u02a5\3\2\2\2\u02a7\u02a8\3\2\2\2\u02a8\u02ab\3\2"+ + "\2\2\u02a9\u02aa\7\37\2\2\u02aa\u02ac\58\35\2\u02ab\u02a9\3\2\2\2\u02ab"+ + "\u02ac\3\2\2\2\u02ac\u02ad\3\2\2\2\u02ad\u02ae\7 \2\2\u02ae\u02b0\3\2"+ + "\2\2\u02af\u028b\3\2\2\2\u02af\u028d\3\2\2\2\u02af\u028e\3\2\2\2\u02af"+ + "\u028f\3\2\2\2\u02af\u0293\3\2\2\2\u02af\u0296\3\2\2\2\u02af\u0297\3\2"+ + "\2\2\u02af\u029b\3\2\2\2\u02af\u029c\3\2\2\2\u02af\u02a0\3\2\2\2\u02b0"+ + "\u02b6\3\2\2\2\u02b1\u02b2\f\f\2\2\u02b2\u02b3\7~\2\2\u02b3\u02b5\5f\64"+ + "\2\u02b4\u02b1\3\2\2\2\u02b5\u02b8\3\2\2\2\u02b6\u02b4\3\2\2\2\u02b6\u02b7"+ + "\3\2\2\2\u02b7I\3\2\2\2\u02b8\u02b6\3\2\2\2\u02b9\u02bd\7\30\2\2\u02ba"+ + "\u02bd\7\26\2\2\u02bb\u02bd\7\27\2\2\u02bc\u02b9\3\2\2\2\u02bc\u02ba\3"+ + "\2\2\2\u02bc\u02bb\3\2\2\2\u02bdK\3\2\2\2\u02be\u02c9\5N(\2\u02bf\u02c0"+ + "\7j\2\2\u02c0\u02c1\5N(\2\u02c1\u02c2\7q\2\2\u02c2\u02c9\3\2\2\2\u02c3"+ + "\u02c9\5P)\2\u02c4\u02c5\7j\2\2\u02c5\u02c6\5P)\2\u02c6\u02c7\7q\2\2\u02c7"+ + "\u02c9\3\2\2\2\u02c8\u02be\3\2\2\2\u02c8\u02bf\3\2\2\2\u02c8\u02c3\3\2"+ + "\2\2\u02c8\u02c4\3\2\2\2\u02c9M\3\2\2\2\u02ca\u02cb\7\21\2\2\u02cb\u02cc"+ + "\7\3\2\2\u02cc\u02cd\5\66\34\2\u02cd\u02ce\7\f\2\2\u02ce\u02cf\5f\64\2"+ + "\u02cf\u02d0\7\4\2\2\u02d0O\3\2\2\2\u02d1\u02d2\7\25\2\2\u02d2\u02d3\7"+ + "\3\2\2\u02d3\u02d4\5\66\34\2\u02d4\u02d5\7\5\2\2\u02d5\u02d6\5f\64\2\u02d6"+ + "\u02d7\7\4\2\2\u02d7Q\3\2\2\2\u02d8\u02de\5T+\2\u02d9\u02da\7j\2\2\u02da"+ + "\u02db\5T+\2\u02db\u02dc\7q\2\2\u02dc\u02de\3\2\2\2\u02dd\u02d8\3\2\2"+ + "\2\u02dd\u02d9\3\2\2\2\u02deS\3\2\2\2\u02df\u02e0\7%\2\2\u02e0\u02e1\7"+ + "\3\2\2\u02e1\u02e2\5j\66\2\u02e2\u02e3\7*\2\2\u02e3\u02e4\5F$\2\u02e4"+ + "\u02e5\7\4\2\2\u02e5U\3\2\2\2\u02e6\u02ec\5X-\2\u02e7\u02e8\7j\2\2\u02e8"+ + "\u02e9\5X-\2\u02e9\u02ea\7q\2\2\u02ea\u02ec\3\2\2\2\u02eb\u02e6\3\2\2"+ + "\2\u02eb\u02e7\3\2\2\2\u02ecW\3\2\2\2\u02ed\u02ee\5Z.\2\u02ee\u02fa\7"+ + "\3\2\2\u02ef\u02f1\5 \21\2\u02f0\u02ef\3\2\2\2\u02f0\u02f1\3\2\2\2\u02f1"+ + "\u02f2\3\2\2\2\u02f2\u02f7\5\66\34\2\u02f3\u02f4\7\5\2\2\u02f4\u02f6\5"+ + "\66\34\2\u02f5\u02f3\3\2\2\2\u02f6\u02f9\3\2\2\2\u02f7\u02f5\3\2\2\2\u02f7"+ + "\u02f8\3\2\2\2\u02f8\u02fb\3\2\2\2\u02f9\u02f7\3\2\2\2\u02fa\u02f0\3\2"+ + "\2\2\u02fa\u02fb\3\2\2\2\u02fb\u02fc\3\2\2\2\u02fc\u02fd\7\4\2\2\u02fd"+ + "Y\3\2\2\2\u02fe\u0302\7:\2\2\u02ff\u0302\7P\2\2\u0300\u0302\5j\66\2\u0301"+ + "\u02fe\3\2\2\2\u0301\u02ff\3\2\2\2\u0301\u0300\3\2\2\2\u0302[\3\2\2\2"+ + "\u0303\u031e\7E\2\2\u0304\u031e\5b\62\2\u0305\u031e\5r:\2\u0306\u031e"+ + "\5`\61\2\u0307\u0309\7\u0081\2\2\u0308\u0307\3\2\2\2\u0309\u030a\3\2\2"+ + "\2\u030a\u0308\3\2\2\2\u030a\u030b\3\2\2\2\u030b\u031e\3\2\2\2\u030c\u031e"+ + "\7\u0080\2\2\u030d\u030e\7l\2\2\u030e\u030f\5t;\2\u030f\u0310\7q\2\2\u0310"+ + "\u031e\3\2\2\2\u0311\u0312\7m\2\2\u0312\u0313\5t;\2\u0313\u0314\7q\2\2"+ + "\u0314\u031e\3\2\2\2\u0315\u0316\7n\2\2\u0316\u0317\5t;\2\u0317\u0318"+ + "\7q\2\2\u0318\u031e\3\2\2\2\u0319\u031a\7o\2\2\u031a\u031b\5t;\2\u031b"+ + "\u031c\7q\2\2\u031c\u031e\3\2\2\2\u031d\u0303\3\2\2\2\u031d\u0304\3\2"+ + "\2\2\u031d\u0305\3\2\2\2\u031d\u0306\3\2\2\2\u031d\u0308\3\2\2\2\u031d"+ + "\u030c\3\2\2\2\u031d\u030d\3\2\2\2\u031d\u0311\3\2\2\2\u031d\u0315\3\2"+ + "\2\2\u031d\u0319\3\2\2\2\u031e]\3\2\2\2\u031f\u0320\t\r\2\2\u0320_\3\2"+ + "\2\2\u0321\u0322\t\16\2\2\u0322a\3\2\2\2\u0323\u0325\7\66\2\2\u0324\u0326"+ + "\t\7\2\2\u0325\u0324\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u0329\3\2\2\2\u0327"+ + "\u032a\5r:\2\u0328\u032a\5t;\2\u0329\u0327\3\2\2\2\u0329\u0328\3\2\2\2"+ + "\u032a\u032b\3\2\2\2\u032b\u032e\5d\63\2\u032c\u032d\7^\2\2\u032d\u032f"+ + "\5d\63\2\u032e\u032c\3\2\2\2\u032e\u032f\3\2\2\2\u032fc\3\2\2\2\u0330"+ + "\u0331\t\17\2\2\u0331e\3\2\2\2\u0332\u0333\5j\66\2\u0333g\3\2\2\2\u0334"+ + "\u0335\5j\66\2\u0335\u0336\7\177\2\2\u0336\u0338\3\2\2\2\u0337\u0334\3"+ + "\2\2\2\u0338\u033b\3\2\2\2\u0339\u0337\3\2\2\2\u0339\u033a\3\2\2\2\u033a"+ + "\u033c\3\2\2\2\u033b\u0339\3\2\2\2\u033c\u033d\5j\66\2\u033di\3\2\2\2"+ + "\u033e\u0341\5n8\2\u033f\u0341\5p9\2\u0340\u033e\3\2\2\2\u0340\u033f\3"+ + "\2\2\2\u0341k\3\2\2\2\u0342\u0343\5j\66\2\u0343\u0344\7\6\2\2\u0344\u0346"+ + "\3\2\2\2\u0345\u0342\3\2\2\2\u0345\u0346\3\2\2\2\u0346\u0347\3\2\2\2\u0347"+ + "\u034f\7\u0086\2\2\u0348\u0349\5j\66\2\u0349\u034a\7\6\2\2\u034a\u034c"+ + "\3\2\2\2\u034b\u0348\3\2\2\2\u034b\u034c\3\2\2\2\u034c\u034d\3\2\2\2\u034d"+ + "\u034f\5j\66\2\u034e\u0345\3\2\2\2\u034e\u034b\3\2\2\2\u034fm\3\2\2\2"+ + "\u0350\u0353\7\u0087\2\2\u0351\u0353\7\u0088\2\2\u0352\u0350\3\2\2\2\u0352"+ + "\u0351\3\2\2\2\u0353o\3\2\2\2\u0354\u0358\7\u0084\2\2\u0355\u0358\5x="+ + "\2\u0356\u0358\7\u0085\2\2\u0357\u0354\3\2\2\2\u0357\u0355\3\2\2\2\u0357"+ + "\u0356\3\2\2\2\u0358q\3\2\2\2\u0359\u035c\7\u0083\2\2\u035a\u035c\7\u0082"+ + "\2\2\u035b\u0359\3\2\2\2\u035b\u035a\3\2\2\2\u035cs\3\2\2\2\u035d\u035e"+ + "\t\20\2\2\u035eu\3\2\2\2\u035f\u0360\7d\2\2\u0360\u0361\5\66\34\2\u0361"+ + "\u0362\7\\\2\2\u0362\u0363\5\66\34\2\u0363w\3\2\2\2\u0364\u0365\t\21\2"+ + "\2\u0365y\3\2\2\2x\u0089\u008b\u008f\u0098\u009a\u009e\u00a6\u00a8\u00ac"+ + "\u00b0\u00b6\u00ba\u00bf\u00c4\u00c8\u00cc\u00d1\u00db\u00df\u00e7\u00ea"+ + "\u00f0\u00f5\u00f8\u00fd\u0100\u0102\u010a\u010d\u0119\u011c\u011f\u0126"+ + "\u012d\u0131\u0135\u0139\u013c\u0140\u0144\u0149\u014d\u0155\u0159\u015c"+ + "\u0163\u016e\u0171\u0175\u0187\u018c\u018f\u0195\u019c\u01a3\u01a6\u01aa"+ + "\u01ae\u01b2\u01b4\u01bf\u01c4\u01c7\u01cb\u01ce\u01d4\u01d7\u01dd\u01e0"+ + "\u01e2\u01f4\u01f9\u01fc\u021f\u0227\u0229\u0230\u0235\u0238\u0240\u0249"+ + "\u024f\u0257\u025c\u0262\u0265\u026c\u0274\u027a\u0286\u0288\u0293\u02a2"+ + "\u02a7\u02ab\u02af\u02b6\u02bc\u02c8\u02dd\u02eb\u02f0\u02f7\u02fa\u0301"+ + "\u030a\u031d\u0325\u0329\u032e\u0339\u0340\u0345\u034b\u034e\u0352\u0357"+ + "\u035b"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseVisitor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseVisitor.java index 41635c1005c5e..cdf80b11da7ac 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseVisitor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseVisitor.java @@ -71,6 +71,13 @@ interface SqlBaseVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitShowSchemas(SqlBaseParser.ShowSchemasContext ctx); + /** + * Visit a parse tree produced by the {@code showCatalogs} + * labeled alternative in {@link SqlBaseParser#statement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitShowCatalogs(SqlBaseParser.ShowCatalogsContext ctx); /** * Visit a parse tree produced by the {@code sysTables} * labeled alternative in {@link SqlBaseParser#statement}. diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java new file mode 100644 index 0000000000000..1f7eaa7c33ccc --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.plan.logical.command; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.xpack.ql.expression.Attribute; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.session.Cursor.Page; +import org.elasticsearch.xpack.sql.session.SqlSession; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ShowCatalogs extends Command { + + public ShowCatalogs(Source source) { + super(source); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this); + } + + @Override + public List output() { + return Arrays.asList(keyword("name"), keyword("type")); + } + + @Override + public void execute(SqlSession session, ActionListener listener) { + List> rows = new ArrayList<>(); + rows.add(Arrays.asList(session.indexResolver().clusterName(), "local")); + session.indexResolver().remoteClusters().forEach(x -> rows.add(Arrays.asList(x, "remote"))); + listener.onResponse(of(session, rows)); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + return true; + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java index d6a59055e15c8..60ab395ad3edf 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.sql.plan.logical.command; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.ql.expression.Attribute; import org.elasticsearch.xpack.ql.expression.FieldAttribute; import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern; @@ -28,15 +29,20 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class ShowColumns extends Command { + // SYS COLUMNS's catalog "cannot contain a string search pattern" (by xDBC specs). + // SHOW COLUMNS's catalog OTOH, could contain a cluster pattern, suitable to `cluster_pattern:index_pattern` search scoping. + private final String catalog; private final String index; private final LikePattern pattern; private final boolean includeFrozen; - public ShowColumns(Source source, String index, LikePattern pattern, boolean includeFrozen) { + public ShowColumns(Source source, String catalog, String index, LikePattern pattern, boolean includeFrozen) { super(source); + this.catalog = catalog; this.index = index; this.pattern = pattern; this.includeFrozen = includeFrozen; @@ -52,7 +58,7 @@ public LikePattern pattern() { @Override protected NodeInfo info() { - return NodeInfo.create(this, ShowColumns::new, index, pattern, includeFrozen); + return NodeInfo.create(this, ShowColumns::new, catalog, index, pattern, includeFrozen); } @Override @@ -64,11 +70,12 @@ public List output() { @Override public void execute(SqlSession session, ActionListener listener) { + String cluster = session.indexResolver().clusterName(); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); - String regex = pattern != null ? pattern.asJavaRegex() : null; + idx = Strings.hasText(catalog) && catalog.equals(cluster) == false ? buildRemoteIndexName(catalog, idx) : idx; boolean withFrozen = includeFrozen || session.configuration().includeFrozen(); - session.indexResolver().resolveAsMergedMapping(idx, regex, withFrozen, emptyMap(), ActionListener.wrap( + session.indexResolver().resolveAsMergedMapping(idx, withFrozen, emptyMap(), ActionListener.wrap( indexResult -> { List> rows = emptyList(); if (indexResult.isValid()) { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java index c9f59afd73954..cca8341485d8c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java @@ -24,12 +24,17 @@ public class ShowTables extends Command { + private final LikePattern catalogPattern; + private final String catalog; private final String index; private final LikePattern pattern; private final boolean includeFrozen; - public ShowTables(Source source, String index, LikePattern pattern, boolean includeFrozen) { + public ShowTables(Source source, LikePattern catalogPattern, String catalog, String index, LikePattern pattern, + boolean includeFrozen) { super(source); + this.catalogPattern = catalogPattern; + this.catalog = catalog; this.index = index; this.pattern = pattern; this.includeFrozen = includeFrozen; @@ -37,7 +42,7 @@ public ShowTables(Source source, String index, LikePattern pattern, boolean incl @Override protected NodeInfo info() { - return NodeInfo.create(this, ShowTables::new, index, pattern, includeFrozen); + return NodeInfo.create(this, ShowTables::new, catalogPattern, catalog, index, pattern, includeFrozen); } public String index() { @@ -50,21 +55,21 @@ public LikePattern pattern() { @Override public List output() { - return asList(keyword("name"), keyword("type"), keyword("kind")); + return asList(keyword("catalog"), keyword("name"), keyword("type"), keyword("kind")); } @Override public final void execute(SqlSession session, ActionListener listener) { + String cat = catalogPattern != null ? catalogPattern.asIndexNameWildcard() : catalog; String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String regex = pattern != null ? pattern.asJavaRegex() : null; + boolean withFrozen = session.configuration().includeFrozen() || includeFrozen; // to avoid redundancy, indicate whether frozen fields are required by specifying the type - EnumSet withFrozen = session.configuration().includeFrozen() || includeFrozen ? - IndexType.VALID_INCLUDE_FROZEN : IndexType.VALID_REGULAR; - - session.indexResolver().resolveNames(idx, regex, withFrozen, ActionListener.wrap(result -> { + EnumSet indexType = withFrozen ? IndexType.VALID_INCLUDE_FROZEN : IndexType.VALID_REGULAR; + session.indexResolver().resolveNames(cat, idx, regex, indexType, ActionListener.wrap(result -> { listener.onResponse(of(session, result.stream() - .map(t -> asList(t.name(), t.type().toSql(), t.type().toNative())) + .map(t -> asList(t.cluster(), t.name(), t.type().toSql(), t.type().toNative())) .collect(toList()))); }, listener::onFailure)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumns.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumns.java index 039df83ee419f..b1c4847cf8e8a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumns.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumns.java @@ -33,6 +33,10 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; +import static org.elasticsearch.transport.RemoteClusterAware.REMOTE_CLUSTER_INDEX_SEPARATOR; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.isQualified; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; import static org.elasticsearch.xpack.ql.type.DataTypes.BINARY; import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; import static org.elasticsearch.xpack.ql.type.DataTypes.NESTED; @@ -113,12 +117,6 @@ public void execute(SqlSession session, ActionListener listener) { List output = output(mode == Mode.ODBC); String cluster = session.indexResolver().clusterName(); - // bail-out early if the catalog is present but differs - if (Strings.hasText(catalog) && cluster.equals(catalog) == false) { - listener.onResponse(Page.last(Rows.empty(output))); - return; - } - // save original index name (as the pattern can contain special chars) String indexName = index != null ? index : (pattern != null ? StringUtils.likeToUnescaped(pattern.pattern(), pattern.escape()) : ""); @@ -128,26 +126,45 @@ public void execute(SqlSession session, ActionListener listener) { Pattern columnMatcher = columnPattern != null ? Pattern.compile(columnPattern.asJavaRegex()) : null; boolean includeFrozen = session.configuration().includeFrozen(); + // disallow double catalog specification, like: SYS COLUMNS CATALOG 'catA' TABLE LIKE 'catB:index_expression' + if (isQualified(idx)) { + throw new IllegalArgumentException("illegal character [" + REMOTE_CLUSTER_INDEX_SEPARATOR + "] (the catalog delimiter) " + + "found in the table expression [" + idx + "]"); + } + + String indexPattern = idx; + String tableCat; + if (Strings.hasText(catalog)) { + // SYS COLUMNS's catalog "cannot contain a string search pattern" (by xDBC specs) -> it must match local or a remote cluster. + // Require an exact match for local cluster, since a pattern might match local and remote clusters, which cannot be searched. + if (catalog.equals(cluster) == false) { + indexPattern = buildRemoteIndexName(catalog, idx); + } + tableCat = catalog; + } else { + tableCat = cluster; + } + // special case for '%' (translated to *) if ("*".equals(idx)) { - session.indexResolver().resolveAsSeparateMappings(idx, regex, includeFrozen, emptyMap(), + session.indexResolver().resolveAsSeparateMappings(indexPattern, regex, includeFrozen, emptyMap(), ActionListener.wrap(esIndices -> { List> rows = new ArrayList<>(); for (EsIndex esIndex : esIndices) { - fillInRows(cluster, esIndex.name(), esIndex.mapping(), null, rows, columnMatcher, mode); + fillInRows(tableCat, esIndex.name(), esIndex.mapping(), null, rows, columnMatcher, mode); } listener.onResponse(ListCursor.of(Rows.schema(output), rows, session.configuration().pageSize())); }, listener::onFailure)); } // otherwise use a merged mapping else { - session.indexResolver().resolveAsMergedMapping(idx, regex, includeFrozen, emptyMap(), + session.indexResolver().resolveAsMergedMapping(indexPattern, includeFrozen, emptyMap(), ActionListener.wrap(r -> { List> rows = new ArrayList<>(); // populate the data only when a target is found if (r.isValid()) { EsIndex esIndex = r.get(); - fillInRows(cluster, indexName, esIndex.mapping(), null, rows, columnMatcher, mode); + fillInRows(tableCat, indexName, esIndex.mapping(), null, rows, columnMatcher, mode); } listener.onResponse(ListCursor.of(Rows.schema(output), rows, session.configuration().pageSize())); }, listener::onFailure)); @@ -156,7 +173,7 @@ public void execute(SqlSession session, ActionListener listener) { static void fillInRows(String clusterName, String indexName, Map mapping, String prefix, List> rows, Pattern columnMatcher, Mode mode) { - fillInRows(clusterName, indexName, mapping, prefix, rows, columnMatcher, Counter.newCounter(), mode); + fillInRows(clusterName, splitQualifiedIndex(indexName).v2(), mapping, prefix, rows, columnMatcher, Counter.newCounter(), mode); } private static void fillInRows(String clusterName, String indexName, Map mapping, String prefix, List> rows, diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTables.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTables.java index 9014a9fea473d..9da6e6912edc2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTables.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTables.java @@ -15,19 +15,19 @@ import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.sql.plan.logical.command.Command; import org.elasticsearch.xpack.sql.session.Cursor.Page; -import org.elasticsearch.xpack.sql.session.Rows; import org.elasticsearch.xpack.sql.session.SqlSession; import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.regex.Pattern; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.xpack.ql.util.StringUtils.EMPTY; import static org.elasticsearch.xpack.ql.util.StringUtils.SQL_WILDCARD; @@ -77,12 +77,18 @@ public final void execute(SqlSession session, ActionListener listener) { // catalog enumeration if (clusterPattern == null || clusterPattern.pattern().equals(SQL_WILDCARD)) { // enumerate only if pattern is "" and no types are specified (types is null) - if (pattern != null && pattern.pattern().isEmpty() && index == null - && types == null) { - Object[] enumeration = new Object[10]; - // send only the cluster, everything else null - enumeration[0] = cluster; - listener.onResponse(Page.last(Rows.singleton(output(), enumeration))); + if (pattern != null && pattern.pattern().isEmpty() && index == null && types == null) { + // include remote and local cluster + Set clusters = session.indexResolver().remoteClusters(); + clusters.add(cluster); + + List> rows = new ArrayList<>(clusters.size()); + for (String name : clusters) { + List row = new ArrayList<>(10); + row.addAll(Arrays.asList(name, null, null, null, null, null, null, null, null, null)); + rows.add(row); + } + listener.onResponse(of(session, rows)); return; } } @@ -115,15 +121,8 @@ public final void execute(SqlSession session, ActionListener listener) { // no enumeration pattern found, list actual tables - String cRegex = clusterPattern != null ? clusterPattern.asJavaRegex() : null; - - // if the catalog doesn't match, don't return any results - if (cRegex != null && Pattern.matches(cRegex, cluster) == false) { - listener.onResponse(Page.last(Rows.empty(output()))); - return; - } - - String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); + String cRegex = clusterPattern != null ? clusterPattern.asIndexNameWildcard() : null; + String idx = hasText(index) ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String regex = pattern != null ? pattern.asJavaRegex() : null; EnumSet tableTypes = types; @@ -137,12 +136,13 @@ public final void execute(SqlSession session, ActionListener listener) { } } - session.indexResolver().resolveNames(idx, regex, tableTypes, ActionListener.wrap(result -> listener.onResponse( + session.indexResolver().resolveNames(cRegex, idx, regex, tableTypes, ActionListener.wrap(result -> listener.onResponse( of(session, result.stream() - // sort by type, then by name + // sort by type, then by cluster and name .sorted(Comparator. comparing(i -> i.type().toSql()) - .thenComparing(Comparator.comparing(i -> i.name()))) - .map(t -> asList(cluster, + .thenComparing(IndexInfo::cluster) + .thenComparing(IndexInfo::name)) + .map(t -> asList(t.cluster(), null, t.name(), t.type().toSql(), diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java index e5e270c655dbb..fc5350dcb9e1d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java @@ -91,14 +91,16 @@ public Collection createComponents(Client client, ClusterService cluster IndexNameExpressionResolver expressionResolver, Supplier repositoriesServiceSupplier) { - return createComponents(client, clusterService.getClusterName().value(), namedWriteableRegistry); + return createComponents(client, environment.settings(), clusterService, namedWriteableRegistry); } /** * Create components used by the sql plugin. */ - Collection createComponents(Client client, String clusterName, NamedWriteableRegistry namedWriteableRegistry) { - IndexResolver indexResolver = new IndexResolver(client, clusterName, SqlDataTypeRegistry.INSTANCE); + Collection createComponents(Client client, Settings settings, ClusterService clusterService, + NamedWriteableRegistry namedWriteableRegistry) { + IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), settings, + clusterService.getClusterSettings(), SqlDataTypeRegistry.INSTANCE); return Arrays.asList(sqlLicenseChecker, indexResolver, new PlanExecutor(client, indexResolver, namedWriteableRegistry)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java index accd85d60541d..2637c9b4ce2c2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java @@ -35,6 +35,7 @@ import java.util.function.Function; import static org.elasticsearch.action.ActionListener.wrap; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class SqlSession implements Session { @@ -143,13 +144,12 @@ private void preAnalyze(LogicalPlan parsed, Function act String cluster = table.cluster(); - if (Strings.hasText(cluster) && indexResolver.clusterName().equals(cluster) == false) { - listener.onFailure(new MappingException("Cannot inspect indices in cluster/catalog [{}]", cluster)); - } + String indexPattern = Strings.hasText(cluster) && cluster.equals(configuration.clusterName()) == false ? + buildRemoteIndexName(cluster, table.index()) : table.index(); boolean includeFrozen = configuration.includeFrozen() || tableInfo.isFrozen(); - indexResolver.resolveAsMergedMapping(table.index(), null, includeFrozen, configuration.runtimeMappings(), - wrap(indexResult -> listener.onResponse(action.apply(indexResult)), listener::onFailure)); + indexResolver.resolveAsMergedMapping(indexPattern, includeFrozen, + configuration.runtimeMappings(), wrap(indexResult -> listener.onResponse(action.apply(indexResult)), listener::onFailure)); } else { try { // occurs when dealing with local relations (SELECT 5+2) diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java index cc8b5ff137fb3..9b87b14361e45 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java @@ -18,6 +18,8 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.TaskCancelHelper; import org.elasticsearch.tasks.TaskCancelledException; import org.elasticsearch.tasks.TaskId; @@ -223,7 +225,8 @@ private ClusterService mockClusterService(String nodeId) { } private static IndexResolver indexResolver(Client client) { - return new IndexResolver(client, randomAlphaOfLength(10), DefaultDataTypeRegistry.INSTANCE); + return new IndexResolver(client, randomAlphaOfLength(10), Settings.EMPTY, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), DefaultDataTypeRegistry.INSTANCE); } private static SqlQueryTask randomTask() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index c75334356c448..ce7706116c2bd 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -179,7 +179,7 @@ private static FieldAttribute getFieldAttribute(String name) { } public void testPruneSubQueryAliases() { - ShowTables s = new ShowTables(EMPTY, null, null, false); + ShowTables s = new ShowTables(EMPTY, null, null, null,null, false); SubQueryAlias plan = new SubQueryAlias(EMPTY, s, "show"); LogicalPlan result = new PruneSubQueryAliases().apply(plan); assertEquals(result, s); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java index d8d96925e0346..86d75b7691aa9 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import org.elasticsearch.Version; @@ -181,7 +182,7 @@ public void testSysColumnsNoArg() { } public void testSysColumnsWithCatalogWildcard() { - executeCommand("SYS COLUMNS CATALOG 'cluster' TABLE LIKE 'test' LIKE '%'", emptyList(), r -> { + executeCommand("SYS COLUMNS CATALOG '" + CLUSTER_NAME + "' TABLE LIKE 'test' LIKE '%'", emptyList(), r -> { assertEquals(FIELD_COUNT1, r.size()); assertEquals(CLUSTER_NAME, r.column(0)); assertEquals("test", r.column(2)); @@ -276,10 +277,11 @@ private Tuple sql(String sql, List para IndexResolver resolver = mock(IndexResolver.class); when(resolver.clusterName()).thenReturn(CLUSTER_NAME); + when(resolver.remoteClusters()).thenReturn(Set.of(CLUSTER_NAME)); doAnswer(invocation -> { - ((ActionListener) invocation.getArguments()[4]).onResponse(IndexResolution.valid(test)); + ((ActionListener) invocation.getArguments()[3]).onResponse(IndexResolution.valid(test)); return Void.TYPE; - }).when(resolver).resolveAsMergedMapping(any(), any(), anyBoolean(), any(), any()); + }).when(resolver).resolveAsMergedMapping(any(), anyBoolean(), any(), any()); doAnswer(invocation -> { ((ActionListener>) invocation.getArguments()[4]).onResponse(singletonList(test)); return Void.TYPE; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java index a2789ca900b95..21bb856367694 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java @@ -55,9 +55,9 @@ public class SysTablesTests extends ESTestCase { private final SqlParser parser = new SqlParser(); private final Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json", true); - private final IndexInfo index = new IndexInfo("test", IndexType.STANDARD_INDEX); - private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS); - private final IndexInfo frozen = new IndexInfo("frozen", IndexType.FROZEN_INDEX); + private final IndexInfo index = new IndexInfo(CLUSTER_NAME, "test", IndexType.STANDARD_INDEX); + private final IndexInfo alias = new IndexInfo(CLUSTER_NAME, "alias", IndexType.ALIAS); + private final IndexInfo frozen = new IndexInfo(CLUSTER_NAME, "frozen", IndexType.FROZEN_INDEX); private final SqlConfiguration FROZEN_CFG = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, Mode.PLAIN, null, null, null, null, false, true); @@ -149,6 +149,17 @@ public void testSysTablesDifferentCatalog() throws Exception { }); } + public void testSysTablesLocalCatalog() throws Exception { + executeCommand("SYS TABLES CATALOG LIKE '" + CLUSTER_NAME + "'", r -> { + assertEquals(2, r.size()); + assertEquals("test", r.column(2)); + assertEquals(SQL_TABLE, r.column(3)); + assertTrue(r.advanceRow()); + assertEquals("alias", r.column(2)); + assertEquals(SQL_VIEW, r.column(3)); + }, index, alias); + } + public void testSysTablesNoTypes() throws Exception { executeCommand("SYS TABLES", r -> { assertEquals(2, r.size()); @@ -315,12 +326,6 @@ public void testSysTablesWithCatalogOnlyAliases() throws Exception { }, alias); } - public void testSysTablesWithEmptyCatalogOnlyAliases() throws Exception { - executeCommand("SYS TABLES CATALOG LIKE '' LIKE 'test' TYPE 'VIEW'", r -> { - assertEquals(0, r.size()); - }, alias); - } - public void testSysTablesWithInvalidType() throws Exception { executeCommand("SYS TABLES LIKE 'test' TYPE 'QUE HORA ES'", r -> { assertEquals(0, r.size()); @@ -366,9 +371,9 @@ private void executeCommand(String sql, List params, Consume IndexResolver resolver = tuple.v2().indexResolver(); doAnswer(invocation -> { - ((ActionListener) invocation.getArguments()[3]).onResponse(new LinkedHashSet<>(asList(infos))); + ((ActionListener) invocation.getArguments()[4]).onResponse(new LinkedHashSet<>(asList(infos))); return Void.TYPE; - }).when(resolver).resolveNames(any(), any(), any(), any()); + }).when(resolver).resolveNames(any(), any(), any(), any(), any()); tuple.v1().execute(tuple.v2(), wrap(p -> consumer.accept((SchemaRowSet) p.rowSet()), ex -> fail(ex.getMessage()))); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java index 15d345c5acada..894132d1aee60 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java @@ -7,8 +7,10 @@ package org.elasticsearch.xpack.sql.plugin; import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.IndexScopedSettings; @@ -22,13 +24,19 @@ import static org.hamcrest.Matchers.hasSize; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class SqlPluginTests extends ESTestCase { public void testSqlDisabledIsNoOp() { Settings settings = Settings.builder().put("xpack.sql.enabled", false).build(); SqlPlugin plugin = new SqlPlugin(settings); - assertThat(plugin.createComponents(mock(Client.class), "cluster", new NamedWriteableRegistry(Cursors.getNamedWriteables())), + ClusterService clusterService = mock(ClusterService.class); + when(clusterService.getClusterName()).thenReturn(new ClusterName(randomAlphaOfLength(10))); + when(clusterService.getClusterSettings()).thenReturn(new ClusterSettings(Settings.EMPTY, + ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + assertThat(plugin.createComponents(mock(Client.class), Settings.EMPTY, clusterService, + new NamedWriteableRegistry(Cursors.getNamedWriteables())), hasSize(3)); assertThat(plugin.getActions(), hasSize(8)); assertThat( From 330fe9f752e7beaf523836dec02f001cdf1f0bf7 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Mon, 11 Oct 2021 10:01:49 +0200 Subject: [PATCH 02/12] License and WS fixes License and WS fixes. Add a comment. Revert a debugging change. --- .../elasticsearch/xpack/ql/index/EsIndex.java | 22 +- .../xpack/ql/index/IndexResolver.java | 2 + .../qa/jdbc/SpecBaseIntegrationTestCase.java | 3 +- .../server/src/main/resources/alias.csv-spec | 96 +-- .../src/main/resources/command.csv-spec | 270 +++---- .../src/main/resources/docs/docs.csv-spec | 686 +++++++++--------- .../src/main/resources/geo/geosql.csv-spec | 120 +-- x-pack/plugin/sql/src/main/antlr/SqlBase.g4 | 48 +- .../plan/logical/command/ShowCatalogs.java | 5 +- 9 files changed, 618 insertions(+), 634 deletions(-) diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java index d6221f1f3668f..d37f696fa0dee 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/EsIndex.java @@ -6,45 +6,27 @@ */ package org.elasticsearch.xpack.ql.index; -import org.elasticsearch.core.Nullable; import org.elasticsearch.xpack.ql.type.EsField; import java.util.Map; import java.util.Objects; -import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; - public class EsIndex { - @Nullable - private final String cluster; private final String name; private final Map mapping; public EsIndex(String name, Map mapping) { - this(null, name, mapping); - } - - public EsIndex(@Nullable String cluster, String name, Map mapping) { assert name != null; assert mapping != null; - this.cluster = cluster; this.name = name; this.mapping = mapping; } - public String cluster() { - return cluster; - } - public String name() { return name; } - public String qualifiedName() { - return buildRemoteIndexName(cluster, name); - } - public Map mapping() { return mapping; } @@ -56,7 +38,7 @@ public String toString() { @Override public int hashCode() { - return Objects.hash(cluster, name, mapping); + return Objects.hash(name, mapping); } @Override @@ -70,6 +52,6 @@ public boolean equals(Object obj) { } EsIndex other = (EsIndex) obj; - return Objects.equals(cluster, other.cluster) && Objects.equals(name, other.name) && mapping == other.mapping; + return Objects.equals(name, other.name) && mapping == other.mapping; } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java index d6710e7727dc3..cf00f483062a6 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java @@ -299,6 +299,8 @@ private void resolveRemoteIndices(String clusterWildcard, String indexWildcard, for (String indexName : indices) { // TODO: perform two requests w/ & w/o frozen option to retrieve (by diff) the throttling status? Tuple splitRef = splitQualifiedIndex(indexName); + // Field caps on "remote:foo" should always return either empty or remote indices. But in case cluster's + // detail is missing, it's going to be a local index. TODO: why would this happen? String cluster = splitRef.v1() == null ? clusterName : splitRef.v1(); indexInfos.add(new IndexInfo(cluster, splitRef.v2(), IndexType.STANDARD_INDEX)); } diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java index 91e55a705e0b8..a4082eb162cf9 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java @@ -131,8 +131,7 @@ protected Properties connectionProperties() { } protected boolean logEsResultSet() { - // return false; - return true; + return false; } protected void assertResults(ResultSet expected, ResultSet elastic) throws SQLException { diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec index 4178b3c20695b..e5c56644fb925 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec @@ -28,63 +28,63 @@ emp_no:i | first_name:s describeAlias DESCRIBE test_alias; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describePattern DESCRIBE "test_*"; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; showAlias diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec index de65a1c40250d..a06dc0e7cb53e 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/command.csv-spec @@ -9,15 +9,15 @@ showFunctions SHOW FUNCTIONS; name:s | type:s -AVG |AGGREGATE +AVG |AGGREGATE COUNT |AGGREGATE FIRST |AGGREGATE FIRST_VALUE |AGGREGATE LAST |AGGREGATE LAST_VALUE |AGGREGATE MAX |AGGREGATE -MIN |AGGREGATE -SUM |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE KURTOSIS |AGGREGATE MAD |AGGREGATE PERCENTILE |AGGREGATE @@ -64,11 +64,11 @@ DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR DOM |SCALAR -DOW |SCALAR +DOW |SCALAR DOY |SCALAR FORMAT |SCALAR HOUR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR IDOW |SCALAR ISODAYOFWEEK |SCALAR ISODOW |SCALAR @@ -78,16 +78,16 @@ ISO_DAY_OF_WEEK |SCALAR ISO_WEEK_OF_YEAR |SCALAR IW |SCALAR IWOY |SCALAR -MINUTE |SCALAR -MINUTE_OF_DAY |SCALAR -MINUTE_OF_HOUR |SCALAR -MONTH |SCALAR -MONTHNAME |SCALAR -MONTH_NAME |SCALAR -MONTH_OF_YEAR |SCALAR +MINUTE |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MONTH |SCALAR +MONTHNAME |SCALAR +MONTH_NAME |SCALAR +MONTH_OF_YEAR |SCALAR NOW |SCALAR -QUARTER |SCALAR -SECOND |SCALAR +QUARTER |SCALAR +SECOND |SCALAR SECOND_OF_MINUTE |SCALAR TIMESTAMPADD |SCALAR TIMESTAMPDIFF |SCALAR @@ -97,60 +97,60 @@ TIME_PARSE |SCALAR TODAY |SCALAR TO_CHAR |SCALAR WEEK |SCALAR -WEEK_OF_YEAR |SCALAR -YEAR |SCALAR -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR -ATAN2 |SCALAR -CBRT |SCALAR -CEIL |SCALAR -CEILING |SCALAR -COS |SCALAR -COSH |SCALAR -COT |SCALAR -DEGREES |SCALAR -E |SCALAR -EXP |SCALAR -EXPM1 |SCALAR -FLOOR |SCALAR -LOG |SCALAR -LOG10 |SCALAR -MOD |SCALAR -PI |SCALAR -POWER |SCALAR -RADIANS |SCALAR -RAND |SCALAR -RANDOM |SCALAR -ROUND |SCALAR -SIGN |SCALAR -SIGNUM |SCALAR -SIN |SCALAR -SINH |SCALAR -SQRT |SCALAR -TAN |SCALAR +WEEK_OF_YEAR |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +ATAN2 |SCALAR +CBRT |SCALAR +CEIL |SCALAR +CEILING |SCALAR +COS |SCALAR +COSH |SCALAR +COT |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +MOD |SCALAR +PI |SCALAR +POWER |SCALAR +RADIANS |SCALAR +RAND |SCALAR +RANDOM |SCALAR +ROUND |SCALAR +SIGN |SCALAR +SIGNUM |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR TRUNC |SCALAR TRUNCATE |SCALAR ASCII |SCALAR -BIT_LENGTH |SCALAR -CHAR |SCALAR -CHARACTER_LENGTH |SCALAR -CHAR_LENGTH |SCALAR -CONCAT |SCALAR -INSERT |SCALAR -LCASE |SCALAR -LEFT |SCALAR -LENGTH |SCALAR -LOCATE |SCALAR -LTRIM |SCALAR -OCTET_LENGTH |SCALAR -POSITION |SCALAR -REPEAT |SCALAR -REPLACE |SCALAR -RIGHT |SCALAR -RTRIM |SCALAR -SPACE |SCALAR +BIT_LENGTH |SCALAR +CHAR |SCALAR +CHARACTER_LENGTH |SCALAR +CHAR_LENGTH |SCALAR +CONCAT |SCALAR +INSERT |SCALAR +LCASE |SCALAR +LEFT |SCALAR +LENGTH |SCALAR +LOCATE |SCALAR +LTRIM |SCALAR +OCTET_LENGTH |SCALAR +POSITION |SCALAR +REPEAT |SCALAR +REPLACE |SCALAR +RIGHT |SCALAR +RTRIM |SCALAR +SPACE |SCALAR STARTS_WITH |SCALAR SUBSTRING |SCALAR TRIM |SCALAR @@ -213,10 +213,10 @@ DAY_NAME |SCALAR DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR ISODAYOFWEEK |SCALAR ISO_DAY_OF_WEEK|SCALAR -MINUTE_OF_DAY |SCALAR +MINUTE_OF_DAY |SCALAR TODAY |SCALAR ; @@ -296,63 +296,63 @@ integTest |test_emp_copy |TABLE |INDEX describeSimpleLike DESCRIBE LIKE 'test_emp'; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describeMultiLike DESCRIBE LIKE 'test_emp%'; - column | type | mapping + column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -extra |STRUCT |object -extra.info |STRUCT |object -extra.info.gender |VARCHAR |keyword -extra_gender |VARCHAR |keyword -extra_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -null_constant |VARCHAR |keyword -salary |INTEGER |integer -wildcard_name |VARCHAR |keyword +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +extra |STRUCT |object +extra.info |STRUCT |object +extra.info.gender |VARCHAR |keyword +extra_gender |VARCHAR |keyword +extra_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +null_constant |VARCHAR |keyword +salary |INTEGER |integer +wildcard_name |VARCHAR |keyword ; describeSimpleIdentifier @@ -384,23 +384,23 @@ DESCRIBE CATALOG 'integTest' "test_emp"; column | type | mapping ----------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword |VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword |VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer ; @@ -409,7 +409,7 @@ salary |INTEGER |integer describeIncludeExcludeIdentifier-Ignore DESCRIBE "test_*,-test_alias*"; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- birth_date |TIMESTAMP |datetime dep |STRUCT |nested diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec index ec70b9cc9102c..4994663a4c7bc 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/docs/docs.csv-spec @@ -14,25 +14,25 @@ describeTable // tag::describeTable DESCRIBE emp; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword|VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer // end::describeTable ; @@ -41,7 +41,7 @@ salary |INTEGER |integer // tag::describeTableAlias //DESCRIBE employee; -// column | type +// column | type //---------------+--------------- // end::describeTableAlias @@ -49,30 +49,30 @@ salary |INTEGER |integer // // Show columns -// +// showColumns // tag::showColumns SHOW COLUMNS IN emp; - column | type | mapping + column | type | mapping --------------------+---------------+--------------- -birth_date |TIMESTAMP |datetime -dep |STRUCT |nested -dep.dep_id |VARCHAR |keyword -dep.dep_name |VARCHAR |text -dep.dep_name.keyword|VARCHAR |keyword -dep.from_date |TIMESTAMP |datetime -dep.to_date |TIMESTAMP |datetime -emp_no |INTEGER |integer -first_name |VARCHAR |text -first_name.keyword |VARCHAR |keyword -gender |VARCHAR |keyword -hire_date |TIMESTAMP |datetime -languages |TINYINT |byte -last_name |VARCHAR |text -last_name.keyword |VARCHAR |keyword -name |VARCHAR |keyword -salary |INTEGER |integer +birth_date |TIMESTAMP |datetime +dep |STRUCT |nested +dep.dep_id |VARCHAR |keyword +dep.dep_name |VARCHAR |text +dep.dep_name.keyword|VARCHAR |keyword +dep.from_date |TIMESTAMP |datetime +dep.to_date |TIMESTAMP |datetime +emp_no |INTEGER |integer +first_name |VARCHAR |text +first_name.keyword |VARCHAR |keyword +gender |VARCHAR |keyword +hire_date |TIMESTAMP |datetime +languages |TINYINT |byte +last_name |VARCHAR |text +last_name.keyword |VARCHAR |keyword +name |VARCHAR |keyword +salary |INTEGER |integer // end::showColumns ; @@ -81,9 +81,9 @@ salary |INTEGER |integer // tag::showColumnsInAlias //SHOW COLUMNS FROM employee; -// column | type +// column | type //---------------+--------------- - + // end::showColumnsInAlias //; @@ -207,15 +207,15 @@ SHOW FUNCTIONS; name | type -----------------+--------------- -AVG |AGGREGATE +AVG |AGGREGATE COUNT |AGGREGATE FIRST |AGGREGATE FIRST_VALUE |AGGREGATE LAST |AGGREGATE LAST_VALUE |AGGREGATE -MAX |AGGREGATE -MIN |AGGREGATE -SUM |AGGREGATE +MAX |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE KURTOSIS |AGGREGATE MAD |AGGREGATE PERCENTILE |AGGREGATE @@ -262,11 +262,11 @@ DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR DOM |SCALAR -DOW |SCALAR +DOW |SCALAR DOY |SCALAR FORMAT |SCALAR HOUR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR IDOW |SCALAR ISODAYOFWEEK |SCALAR ISODOW |SCALAR @@ -276,16 +276,16 @@ ISO_DAY_OF_WEEK |SCALAR ISO_WEEK_OF_YEAR |SCALAR IW |SCALAR IWOY |SCALAR -MINUTE |SCALAR -MINUTE_OF_DAY |SCALAR -MINUTE_OF_HOUR |SCALAR -MONTH |SCALAR -MONTHNAME |SCALAR -MONTH_NAME |SCALAR +MINUTE |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MONTH |SCALAR +MONTHNAME |SCALAR +MONTH_NAME |SCALAR MONTH_OF_YEAR |SCALAR NOW |SCALAR -QUARTER |SCALAR -SECOND |SCALAR +QUARTER |SCALAR +SECOND |SCALAR SECOND_OF_MINUTE |SCALAR TIMESTAMPADD |SCALAR TIMESTAMPDIFF |SCALAR @@ -295,60 +295,60 @@ TIME_PARSE |SCALAR TODAY |SCALAR TO_CHAR |SCALAR WEEK |SCALAR -WEEK_OF_YEAR |SCALAR -YEAR |SCALAR -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR -ATAN2 |SCALAR -CBRT |SCALAR -CEIL |SCALAR -CEILING |SCALAR -COS |SCALAR -COSH |SCALAR -COT |SCALAR -DEGREES |SCALAR -E |SCALAR -EXP |SCALAR -EXPM1 |SCALAR -FLOOR |SCALAR -LOG |SCALAR -LOG10 |SCALAR -MOD |SCALAR -PI |SCALAR -POWER |SCALAR -RADIANS |SCALAR -RAND |SCALAR -RANDOM |SCALAR -ROUND |SCALAR -SIGN |SCALAR -SIGNUM |SCALAR -SIN |SCALAR -SINH |SCALAR -SQRT |SCALAR -TAN |SCALAR +WEEK_OF_YEAR |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +ATAN2 |SCALAR +CBRT |SCALAR +CEIL |SCALAR +CEILING |SCALAR +COS |SCALAR +COSH |SCALAR +COT |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +MOD |SCALAR +PI |SCALAR +POWER |SCALAR +RADIANS |SCALAR +RAND |SCALAR +RANDOM |SCALAR +ROUND |SCALAR +SIGN |SCALAR +SIGNUM |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR TRUNC |SCALAR TRUNCATE |SCALAR ASCII |SCALAR -BIT_LENGTH |SCALAR -CHAR |SCALAR -CHARACTER_LENGTH |SCALAR -CHAR_LENGTH |SCALAR -CONCAT |SCALAR -INSERT |SCALAR -LCASE |SCALAR -LEFT |SCALAR -LENGTH |SCALAR -LOCATE |SCALAR -LTRIM |SCALAR -OCTET_LENGTH |SCALAR -POSITION |SCALAR -REPEAT |SCALAR -REPLACE |SCALAR -RIGHT |SCALAR -RTRIM |SCALAR -SPACE |SCALAR +BIT_LENGTH |SCALAR +CHAR |SCALAR +CHARACTER_LENGTH |SCALAR +CHAR_LENGTH |SCALAR +CONCAT |SCALAR +INSERT |SCALAR +LCASE |SCALAR +LEFT |SCALAR +LENGTH |SCALAR +LOCATE |SCALAR +LTRIM |SCALAR +OCTET_LENGTH |SCALAR +POSITION |SCALAR +REPEAT |SCALAR +REPLACE |SCALAR +RIGHT |SCALAR +RTRIM |SCALAR +SPACE |SCALAR STARTS_WITH |SCALAR SUBSTRING |SCALAR TRIM |SCALAR @@ -374,9 +374,9 @@ showFunctionsLikeExact // tag::showFunctionsLikeExact SHOW FUNCTIONS LIKE 'ABS'; - name | type + name | type ---------------+--------------- -ABS |SCALAR +ABS |SCALAR // end::showFunctionsLikeExact ; @@ -385,15 +385,15 @@ showFunctionsLikeWildcard // tag::showFunctionsLikeWildcard SHOW FUNCTIONS LIKE 'A%'; - name | type + name | type ---------------+--------------- -AVG |AGGREGATE -ABS |SCALAR -ACOS |SCALAR -ASIN |SCALAR -ATAN |SCALAR +AVG |AGGREGATE +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR ATAN2 |SCALAR -ASCII |SCALAR +ASCII |SCALAR // end::showFunctionsLikeWildcard ; @@ -401,10 +401,10 @@ showFunctionsLikeChar // tag::showFunctionsLikeChar SHOW FUNCTIONS LIKE 'A__'; - name | type + name | type ---------------+--------------- -AVG |AGGREGATE -ABS |SCALAR +AVG |AGGREGATE +ABS |SCALAR // end::showFunctionsLikeChar ; @@ -412,7 +412,7 @@ showFunctionsWithPattern // tag::showFunctionsWithPattern SHOW FUNCTIONS LIKE '%DAY%'; - name | type + name | type ---------------+--------------- DAY |SCALAR DAYNAME |SCALAR @@ -423,10 +423,10 @@ DAY_NAME |SCALAR DAY_OF_MONTH |SCALAR DAY_OF_WEEK |SCALAR DAY_OF_YEAR |SCALAR -HOUR_OF_DAY |SCALAR +HOUR_OF_DAY |SCALAR ISODAYOFWEEK |SCALAR ISO_DAY_OF_WEEK|SCALAR -MINUTE_OF_DAY |SCALAR +MINUTE_OF_DAY |SCALAR TODAY |SCALAR // end::showFunctionsWithPattern @@ -442,9 +442,9 @@ selectColumnAlias // tag::selectColumnAlias SELECT 1 + 1 AS result; - result + result --------------- -2 +2 // end::selectColumnAlias ; @@ -453,9 +453,9 @@ selectInline // tag::selectInline SELECT 1 + 1; - 1 + 1 + 1 + 1 -------------- -2 +2 // end::selectInline ; @@ -464,9 +464,9 @@ selectColumn // tag::selectColumn SELECT emp_no FROM emp LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::selectColumn ; @@ -475,9 +475,9 @@ selectQualifiedColumn // tag::selectQualifiedColumn SELECT emp.emp_no FROM emp LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::selectQualifiedColumn ; @@ -487,7 +487,7 @@ wildcardWithOrder // tag::wildcardWithOrder SELECT * FROM emp LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 @@ -498,10 +498,10 @@ fromTable // tag::fromTable SELECT * FROM emp LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 - + // end::fromTable ; @@ -510,7 +510,7 @@ fromTableQuoted // tag::fromTableQuoted SELECT * FROM "emp" LIMIT 1; - birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary + birth_date | emp_no | first_name | gender | hire_date | languages | last_name | name | salary --------------------+---------------+---------------+---------------+------------------------+---------------+---------------+---------------+--------------- 1953-09-02T00:00:00Z|10001 |Georgi |M |1986-06-26T00:00:00.000Z|2 |Facello |Georgi Facello |57305 @@ -521,7 +521,7 @@ fromTableIncludeFrozen // tag::fromTableIncludeFrozen SELECT * FROM FROZEN archive LIMIT 1; - author | name | page_count | release_date + author | name | page_count | release_date -----------------+--------------------+---------------+-------------------- James S.A. Corey |Leviathan Wakes |561 |2011-06-02T00:00:00Z @@ -532,9 +532,9 @@ fromTableQuoted // tag::fromTablePatternQuoted SELECT emp_no FROM "e*p" LIMIT 1; - emp_no + emp_no --------------- -10001 +10001 // end::fromTablePatternQuoted ; @@ -543,9 +543,9 @@ fromTableAlias // tag::fromTableAlias SELECT e.emp_no FROM emp AS e LIMIT 1; - emp_no + emp_no ------------- -10001 +10001 // end::fromTableAlias ; @@ -554,9 +554,9 @@ basicWhere // tag::basicWhere SELECT last_name FROM emp WHERE emp_no = 10001; - last_name + last_name --------------- -Facello +Facello // end::basicWhere ; @@ -572,7 +572,7 @@ schema::g:s // tag::groupByColumn SELECT gender AS g FROM emp GROUP BY gender; - g + g --------------- null F @@ -586,11 +586,11 @@ schema::gender:s // tag::groupByOrdinal SELECT gender FROM emp GROUP BY 1; - gender + gender --------------- null -F -M +F +M // end::groupByOrdinal ; @@ -600,11 +600,11 @@ schema::g:s // tag::groupByAlias SELECT gender AS g FROM emp GROUP BY g; - g + g --------------- null -F -M +F +M // end::groupByAlias ; @@ -613,15 +613,15 @@ groupByExpression // tag::groupByExpression SELECT languages + 1 AS l FROM emp GROUP BY l; - l + l --------------- null -2 -3 -4 -5 -6 - +2 +3 +4 +5 +6 + // end::groupByExpression ; @@ -631,24 +631,24 @@ schema::g:s|l:i|c:l // tag::groupByMulti SELECT gender g, languages l, COUNT(*) c FROM "emp" GROUP BY g, l ORDER BY languages ASC, gender DESC; - g | l | c + g | l | c ---------------+---------------+--------------- -M |null |7 -F |null |3 -M |1 |9 -F |1 |4 -null |1 |2 -M |2 |11 -F |2 |5 -null |2 |3 -M |3 |11 -F |3 |6 -M |4 |11 -F |4 |6 -null |4 |1 -M |5 |8 -F |5 |9 -null |5 |4 +M |null |7 +F |null |3 +M |1 |9 +F |1 |4 +null |1 |2 +M |2 |11 +F |2 |5 +null |2 |3 +M |3 |11 +F |3 |6 +M |4 |11 +F |4 |6 +null |4 |1 +M |5 |8 +F |5 |9 +null |5 |4 // end::groupByMulti @@ -660,11 +660,11 @@ schema::g:s|c:i // tag::groupByAndAgg SELECT gender AS g, COUNT(*) AS c FROM emp GROUP BY gender; - g | c + g | c ---------------+--------------- -null |10 -F |33 -M |57 +null |10 +F |33 +M |57 // end::groupByAndAgg ; @@ -674,7 +674,7 @@ schema::g:s|salary:i // tag::groupByAndAggExpression SELECT gender AS g, ROUND((MIN(salary) / 100)) AS salary FROM emp GROUP BY gender; - g | salary + g | salary ---------------+--------------- null |253 F |259 @@ -687,11 +687,11 @@ schema::g:s|k:d|s:d // tag::groupByAndMultipleAggs SELECT gender AS g, KURTOSIS(salary) AS k, SKEWNESS(salary) AS s FROM emp GROUP BY gender; - g | k | s + g | k | s ---------------+------------------+------------------- null |2.2215791166941923|-0.03373126000214023 -F |1.7873117044424276|0.05504995122217512 -M |2.280646181070106 |0.44302407229580243 +F |1.7873117044424276|0.05504995122217512 +M |2.280646181070106 |0.44302407229580243 // end::groupByAndMultipleAggs @@ -701,9 +701,9 @@ groupByImplicitCount // tag::groupByImplicitCount SELECT COUNT(*) AS count FROM emp; - count + count --------------- -100 +100 // end::groupByImplicitCount ; @@ -718,12 +718,12 @@ groupByHaving // tag::groupByHaving SELECT languages AS l, COUNT(*) AS c FROM emp GROUP BY l HAVING c BETWEEN 15 AND 20; - l | c + l | c ---------------+--------------- -1 |15 -2 |19 -3 |17 -4 |18 +1 |15 +2 |19 +3 |17 +4 |18 // end::groupByHaving ; @@ -732,14 +732,14 @@ groupByHavingMultiple // tag::groupByHavingMultiple SELECT MIN(salary) AS min, MAX(salary) AS max, MAX(salary) - MIN(salary) AS diff FROM emp GROUP BY languages HAVING diff - max % min > 0 AND AVG(salary) > 30000; - min | max | diff + min | max | diff ---------------+---------------+--------------- -28336 |74999 |46663 -25976 |73717 |47741 -29175 |73578 |44403 -26436 |74970 |48534 -27215 |74572 |47357 -25324 |66817 |41493 +28336 |74999 |46663 +25976 |73717 |47741 +29175 |73578 |44403 +26436 |74970 |48534 +27215 |74572 |47357 +25324 |66817 |41493 // end::groupByHavingMultiple @@ -749,9 +749,9 @@ groupByImplicitMultipleAggs // tag::groupByImplicitMultipleAggs SELECT MIN(salary) AS min, MAX(salary) AS max, AVG(salary) AS avg, COUNT(*) AS count FROM emp; - min:i | max:i | avg:d | count:l + min:i | max:i | avg:d | count:l ---------------+---------------+---------------+--------------- -25324 |74999 |48248.55 |100 +25324 |74999 |48248.55 |100 // end::groupByImplicitMultipleAggs ; @@ -760,9 +760,9 @@ groupByHavingImplicitMatch // tag::groupByHavingImplicitMatch SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING min > 25000; - min | max + min | max ---------------+--------------- -25324 |74999 +25324 |74999 // end::groupByHavingImplicitMatch ; @@ -771,7 +771,7 @@ SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING min > 25000; // tag::groupByHavingImplicitNoMatch //SELECT MIN(salary) AS min, MAX(salary) AS max FROM emp HAVING max > 75000; -// min | max +// min | max //---------------+--------------- // end::groupByHavingImplicitNoMatch @@ -789,20 +789,20 @@ histogramNumeric // tag::histogramNumeric SELECT HISTOGRAM(salary, 5000) AS h FROM emp GROUP BY h; - h ---------------- -25000 -30000 -35000 -40000 -45000 -50000 -55000 -60000 -65000 + h +--------------- +25000 +30000 +35000 +40000 +45000 +50000 +55000 +60000 +65000 70000 -// end::histogramNumeric +// end::histogramNumeric ; histogramNumericExpression @@ -810,20 +810,20 @@ schema::h:i|c:l // tag::histogramNumericExpression SELECT HISTOGRAM(salary % 100, 10) AS h, COUNT(*) AS c FROM emp GROUP BY h; - h | c + h | c ---------------+--------------- -0 |10 -10 |15 -20 |10 -30 |14 -40 |9 -50 |9 -60 |8 -70 |13 -80 |3 -90 |9 +0 |10 +10 |15 +20 |10 +30 |14 +40 |9 +50 |9 +60 |8 +70 |13 +80 |3 +90 |9 -// end::histogramNumericExpression +// end::histogramNumericExpression ; histogramDateTime @@ -832,23 +832,23 @@ schema::h:ts|c:l SELECT HISTOGRAM(birth_date, INTERVAL 1 YEAR) AS h, COUNT(*) AS c FROM emp GROUP BY h; - h | c + h | c ------------------------+--------------- -null |10 -1952-01-01T00:00:00.000Z|8 -1953-01-01T00:00:00.000Z|11 -1954-01-01T00:00:00.000Z|8 -1955-01-01T00:00:00.000Z|4 -1956-01-01T00:00:00.000Z|5 -1957-01-01T00:00:00.000Z|4 -1958-01-01T00:00:00.000Z|7 -1959-01-01T00:00:00.000Z|9 -1960-01-01T00:00:00.000Z|8 -1961-01-01T00:00:00.000Z|8 -1962-01-01T00:00:00.000Z|6 -1963-01-01T00:00:00.000Z|7 -1964-01-01T00:00:00.000Z|4 -1965-01-01T00:00:00.000Z|1 +null |10 +1952-01-01T00:00:00.000Z|8 +1953-01-01T00:00:00.000Z|11 +1954-01-01T00:00:00.000Z|8 +1955-01-01T00:00:00.000Z|4 +1956-01-01T00:00:00.000Z|5 +1957-01-01T00:00:00.000Z|4 +1958-01-01T00:00:00.000Z|7 +1959-01-01T00:00:00.000Z|9 +1960-01-01T00:00:00.000Z|8 +1961-01-01T00:00:00.000Z|8 +1962-01-01T00:00:00.000Z|6 +1963-01-01T00:00:00.000Z|7 +1964-01-01T00:00:00.000Z|4 +1965-01-01T00:00:00.000Z|1 // end::histogramDateTime ; @@ -863,16 +863,16 @@ schema::h:i|c:l // tag::histogramDateTimeExpression SELECT HISTOGRAM(MONTH(birth_date), 2) AS h, COUNT(*) as c FROM emp GROUP BY h ORDER BY h DESC; - h | c + h | c ---------------+--------------- -12 |7 -10 |17 -8 |16 -6 |16 -4 |18 -2 |10 -0 |6 -null |10 +12 |7 +10 |17 +8 |16 +6 |16 +4 |18 +2 |10 +0 |6 +null |10 // end::histogramDateTimeExpression ; @@ -925,7 +925,7 @@ dtDateTimePlusInterval // tag::dtDateTimePlusInterval SELECT CAST('1969-05-13T12:34:56' AS DATETIME) + INTERVAL 49 YEARS AS result; - result + result -------------------- 2018-05-13T12:34:56Z // end::dtDateTimePlusInterval @@ -935,9 +935,9 @@ dtMinusInterval // tag::dtMinusInterval SELECT - INTERVAL '49-1' YEAR TO MONTH result; - result + result --------------- --49-1 +-49-1 // end::dtMinusInterval ; @@ -957,7 +957,7 @@ dtDateTimeMinusInterval // tag::dtDateTimeMinusInterval SELECT CAST('2018-05-13T12:34:56' AS DATETIME) - INTERVAL '2-8' YEAR TO MONTH AS result; - result + result -------------------- 2015-09-13T12:34:56Z // end::dtDateTimeMinusInterval @@ -967,9 +967,9 @@ dtIntervalMul // tag::dtIntervalMul SELECT -2 * INTERVAL '3' YEARS AS result; - result + result --------------- --6-0 +-6-0 // end::dtIntervalMul ; @@ -984,7 +984,7 @@ orderByBasic // tag::orderByBasic SELECT * FROM library ORDER BY page_count DESC LIMIT 5; - author | name | page_count | release_date + author | name | page_count | release_date -----------------+--------------------+---------------+-------------------- Peter F. Hamilton|Pandora's Star |768 |2004-03-02T00:00:00Z Vernor Vinge |A Fire Upon the Deep|613 |1992-06-01T00:00:00Z @@ -1000,12 +1000,12 @@ schema::g:s|c:i // tag::orderByGroup SELECT gender AS g, COUNT(*) AS c FROM emp GROUP BY gender ORDER BY g DESC; - g | c + g | c ---------------+--------------- M |57 -F |33 -null |10 - +F |33 +null |10 + // end::orderByGroup ; @@ -1014,12 +1014,12 @@ schema::g:s|salary:i // tag::orderByAgg SELECT gender AS g, MIN(salary) AS salary FROM emp GROUP BY gender ORDER BY salary DESC; - g | salary + g | salary ---------------+--------------- -F |25976 -M |25945 -null |25324 - +F |25976 +M |25945 +null |25324 + // end::orderByAgg ; @@ -1106,7 +1106,7 @@ orderByScore // tag::orderByScore SELECT SCORE(), * FROM library WHERE MATCH(name, 'dune') ORDER BY SCORE() DESC; - SCORE() | author | name | page_count | release_date + SCORE() | author | name | page_count | release_date ---------------+---------------+-------------------+---------------+-------------------- 2.2886353 |Frank Herbert |Dune |604 |1965-06-01T00:00:00Z 1.8893257 |Frank Herbert |Dune Messiah |331 |1969-10-15T00:00:00Z @@ -1120,7 +1120,7 @@ orderByScoreWithMatch // tag::orderByScoreWithMatch SELECT SCORE(), * FROM library WHERE MATCH(name, 'dune') ORDER BY page_count DESC; - SCORE() | author | name | page_count | release_date + SCORE() | author | name | page_count | release_date ---------------+---------------+-------------------+---------------+-------------------- 2.2886353 |Frank Herbert |Dune |604 |1965-06-01T00:00:00Z 1.4005898 |Frank Herbert |God Emperor of Dune|454 |1981-05-28T00:00:00Z @@ -1134,7 +1134,7 @@ scoreWithMatch // tag::scoreWithMatch SELECT SCORE() AS score, name, release_date FROM library WHERE QUERY('dune') ORDER BY YEAR(release_date) DESC; - score | name | release_date + score | name | release_date ---------------+-------------------+-------------------- 1.4005898 |God Emperor of Dune|1981-05-28T00:00:00Z 1.6086556 |Children of Dune |1976-04-21T00:00:00Z @@ -1154,9 +1154,9 @@ limitBasic // tag::limitBasic SELECT first_name, last_name, emp_no FROM emp LIMIT 1; - first_name | last_name | emp_no + first_name | last_name | emp_no ---------------+---------------+--------------- -Georgi |Facello |10001 +Georgi |Facello |10001 // end::limitBasic ; @@ -1205,9 +1205,9 @@ aggCountStar // tag::aggCountStar SELECT COUNT(*) AS count FROM emp; - count + count --------------- -100 +100 // end::aggCountStar ; @@ -1215,9 +1215,9 @@ aggCountAll // tag::aggCountAll SELECT COUNT(ALL last_name) AS count_all, COUNT(DISTINCT last_name) count_distinct FROM emp; - count_all | count_distinct + count_all | count_distinct ---------------+------------------ -100 |96 +100 |96 // end::aggCountAll ; @@ -1416,9 +1416,9 @@ aggMax // tag::aggMax SELECT MAX(salary) AS max FROM emp; - max + max --------------- -74999 +74999 // end::aggMax ; @@ -1437,9 +1437,9 @@ aggMin // tag::aggMin SELECT MIN(salary) AS min FROM emp; - min + min --------------- -25324 +25324 // end::aggMin ; @@ -1479,7 +1479,7 @@ aggKurtosis // tag::aggKurtosis SELECT MIN(salary) AS min, MAX(salary) AS max, KURTOSIS(salary) AS k FROM emp; - min | max | k + min | max | k ---------------+---------------+------------------ 25324 |74999 |2.0444718929142986 // end::aggKurtosis @@ -1489,9 +1489,9 @@ aggMad // tag::aggMad SELECT MIN(salary) AS min, MAX(salary) AS max, AVG(salary) AS avg, MAD(salary) AS mad FROM emp; - min | max | avg | mad + min | max | avg | mad ---------------+---------------+---------------+--------------- -25324 |74999 |48248.55 |10096.5 +25324 |74999 |48248.55 |10096.5 // end::aggMad ; @@ -1508,17 +1508,17 @@ SELECT MIN(salary / 12.0) AS min, MAX(salary / 12.0) AS max, AVG(salary/ 12.0) A aggPercentile // tag::aggPercentile -SELECT languages, PERCENTILE(salary, 95) AS "95th" FROM emp +SELECT languages, PERCENTILE(salary, 95) AS "95th" FROM emp GROUP BY languages; - languages | 95th + languages | 95th ---------------+----------------- -null |74999.0 -1 |72790.5 +null |74999.0 +1 |72790.5 2 |71924.70000000001 -3 |73638.25 +3 |73638.25 4 |72115.59999999999 -5 |61071.7 +5 |61071.7 // end::aggPercentile ; @@ -1542,20 +1542,20 @@ null |6249.916666666667 aggPercentileWithPercentileConfig // tag::aggPercentileWithPercentileConfig SELECT - languages, - PERCENTILE(salary, 97.3, 'tdigest', 100.0) AS "97.3_TDigest", - PERCENTILE(salary, 97.3, 'hdr', 3) AS "97.3_HDR" -FROM emp + languages, + PERCENTILE(salary, 97.3, 'tdigest', 100.0) AS "97.3_TDigest", + PERCENTILE(salary, 97.3, 'hdr', 3) AS "97.3_HDR" +FROM emp GROUP BY languages; - languages | 97.3_TDigest | 97.3_HDR + languages | 97.3_TDigest | 97.3_HDR ---------------+---------------+--------------- -null |74999.0 |74992.0 -1 |73717.0 |73712.0 -2 |73530.238 |69936.0 -3 |74970.0 |74992.0 -4 |74572.0 |74608.0 -5 |66117.118 |56368.0 +null |74999.0 |74992.0 +1 |73717.0 |73712.0 +2 |73530.238 |69936.0 +3 |74970.0 |74992.0 +4 |74572.0 |74608.0 +5 |66117.118 |56368.0 // end::aggPercentileWithPercentileConfig ; @@ -1563,14 +1563,14 @@ aggPercentileRank // tag::aggPercentileRank SELECT languages, PERCENTILE_RANK(salary, 65000) AS rank FROM emp GROUP BY languages; - languages | rank + languages | rank ---------------+----------------- null |73.65766569962062 -1 |73.7291625157734 +1 |73.7291625157734 2 |88.88005607010643 3 |79.43662623295829 4 |85.70446389643493 -5 |100.0 +5 |100.0 // end::aggPercentileRank ; @@ -1599,14 +1599,14 @@ SELECT FROM emp GROUP BY languages; - languages | rank_TDigest | rank_HDR + languages | rank_TDigest | rank_HDR ---------------+---------------+--------------- -null |73.66 |80.0 -1 |73.73 |73.33 -2 |88.88 |89.47 -3 |79.44 |76.47 -4 |85.7 |83.33 -5 |100.0 |95.24 +null |73.66 |80.0 +1 |73.73 |73.33 +2 |88.88 |89.47 +3 |79.44 |76.47 +4 |85.7 |83.33 +5 |100.0 |95.24 // end::aggPercentileRankWithPercentileConfig ; @@ -1614,7 +1614,7 @@ aggSkewness // tag::aggSkewness SELECT MIN(salary) AS min, MAX(salary) AS max, SKEWNESS(salary) AS s FROM emp; - min | max | s + min | max | s ---------------+---------------+------------------ 25324 |74999 |0.2707722118423227 // end::aggSkewness @@ -1665,10 +1665,10 @@ SELECT MIN(salary / 12.0) AS min, MAX(salary / 12.0) AS max, STDDEV_SAMP(salary aggSumOfSquares // tag::aggSumOfSquares -SELECT MIN(salary) AS min, MAX(salary) AS max, SUM_OF_SQUARES(salary) AS sumsq +SELECT MIN(salary) AS min, MAX(salary) AS max, SUM_OF_SQUARES(salary) AS sumsq FROM emp; - min | max | sumsq + min | max | sumsq ---------------+---------------+---------------- 25324 |74999 |2.51740125721E11 // end::aggSumOfSquares @@ -1689,7 +1689,7 @@ aggVarPop // tag::aggVarPop SELECT MIN(salary) AS min, MAX(salary) AS max, VAR_POP(salary) AS varpop FROM emp; - min | max | varpop + min | max | varpop ---------------+---------------+---------------- 25324 |74999 |1.894786801075E8 // end::aggVarPop @@ -1738,9 +1738,9 @@ stringAscii // tag::stringAscii SELECT ASCII('Elastic'); -ASCII('Elastic') +ASCII('Elastic') ---------------- -69 +69 // end::stringAscii ; @@ -1750,7 +1750,7 @@ SELECT BIT_LENGTH('Elastic'); BIT_LENGTH('Elastic') --------------------- -56 +56 // end::stringBitLength ; @@ -1758,9 +1758,9 @@ stringChar // tag::stringChar SELECT CHAR(69); - CHAR(69) + CHAR(69) --------------- -E +E // end::stringChar ; @@ -1770,7 +1770,7 @@ SELECT CHAR_LENGTH('Elastic'); CHAR_LENGTH('Elastic') ---------------------- -7 +7 // end::stringCharLength ; @@ -1780,7 +1780,7 @@ SELECT CONCAT('Elasticsearch', ' SQL'); CONCAT('Elasticsearch', ' SQL') ------------------------------- -Elasticsearch SQL +Elasticsearch SQL // end::stringConcat ; @@ -1800,7 +1800,7 @@ SELECT LCASE('Elastic'); LCASE('Elastic') ---------------- -elastic +elastic // end::stringLCase ; @@ -1810,7 +1810,7 @@ SELECT LEFT('Elastic',3); LEFT('Elastic',3) ----------------- -Ela +Ela // end::stringLeft ; @@ -1820,7 +1820,7 @@ SELECT LENGTH('Elastic '); LENGTH('Elastic ') -------------------- -7 +7 // end::stringLength ; @@ -1830,7 +1830,7 @@ SELECT LOCATE('a', 'Elasticsearch'); LOCATE('a', 'Elasticsearch') ---------------------------- -3 +3 // end::stringLocateWoStart ; @@ -1850,7 +1850,7 @@ SELECT LTRIM(' Elastic'); LTRIM(' Elastic') ------------------- -Elastic +Elastic // end::stringLTrim ; @@ -1860,7 +1860,7 @@ SELECT OCTET_LENGTH('Elastic'); OCTET_LENGTH('Elastic') ----------------------- -7 +7 // end::stringOctetLength ; @@ -1870,7 +1870,7 @@ SELECT POSITION('Elastic', 'Elasticsearch'); POSITION('Elastic', 'Elasticsearch') ------------------------------------ -1 +1 // end::stringPosition ; @@ -1878,9 +1878,9 @@ stringRepeat // tag::stringRepeat SELECT REPEAT('La', 3); - REPEAT('La', 3) + REPEAT('La', 3) ---------------- -LaLaLa +LaLaLa // end::stringRepeat ; @@ -1900,7 +1900,7 @@ SELECT RIGHT('Elastic',3); RIGHT('Elastic',3) ------------------ -tic +tic // end::stringRight ; @@ -1910,7 +1910,7 @@ SELECT RTRIM('Elastic '); RTRIM('Elastic ') ------------------- -Elastic +Elastic // end::stringRTrim ; @@ -1919,10 +1919,10 @@ schema::SPACE(3):s // tag::stringSpace SELECT SPACE(3); - SPACE(3) + SPACE(3) --------------- - - + + // end::stringSpace ; @@ -1932,7 +1932,7 @@ SELECT STARTS_WITH('Elasticsearch', 'Elastic'); STARTS_WITH('Elasticsearch', 'Elastic') -------------------------------- -true +true // end::stringStartsWithTrue ; @@ -1942,7 +1942,7 @@ SELECT STARTS_WITH('Elasticsearch', 'ELASTIC'); STARTS_WITH('Elasticsearch', 'ELASTIC') -------------------------------- -false +false // end::stringStartsWithFalse ; @@ -1952,7 +1952,7 @@ SELECT SUBSTRING('Elasticsearch', 0, 7); SUBSTRING('Elasticsearch', 0, 7) -------------------------------- -Elastic +Elastic // end::stringSubString ; @@ -1970,9 +1970,9 @@ stringUCase // tag::stringUCase SELECT UCASE('Elastic'); -UCASE('Elastic') +UCASE('Elastic') ---------------- -ELASTIC +ELASTIC // end::stringUCase ; @@ -1987,9 +1987,9 @@ conversionStringToIntCast // tag::conversionStringToIntCast SELECT CAST('123' AS INT) AS int; - int + int --------------- -123 +123 // end::conversionStringToIntCast ; @@ -1998,9 +1998,9 @@ schema::string:s // tag::conversionIntToStringCast SELECT CAST(123 AS VARCHAR) AS string; - string + string --------------- -123 +123 // end::conversionIntToStringCast ; @@ -3416,7 +3416,7 @@ currentTimestamp-Ignore // tag::curTs SELECT CURRENT_TIMESTAMP AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::curTs @@ -3426,7 +3426,7 @@ currentTimestampFunction-Ignore // tag::curTsFunction SELECT CURRENT_TIMESTAMP() AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::curTsFunction @@ -3436,7 +3436,7 @@ currentTimestampFunctionPrecision-Ignore // tag::curTsFunctionPrecision SELECT CURRENT_TIMESTAMP(1) AS result; - result + result ------------------------ 2018-12-12T14:48:52.4Z // end::curTsFunctionPrecision @@ -3447,7 +3447,7 @@ nowFunction-Ignore // tag::nowFunction SELECT NOW() AS result; - result + result ------------------------ 2018-12-12T14:48:52.448Z // end::nowFunction diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec b/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec index 090baaaf54cdf..a8ebe6079fc5f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec +++ b/x-pack/plugin/sql/qa/server/src/main/resources/geo/geosql.csv-spec @@ -33,21 +33,21 @@ selectAllPointsAsStrings SELECT city, CAST(location AS STRING) location, CAST(location_no_dv AS STRING) location_no_dv, CAST(geoshape AS STRING) geoshape, CAST(shape AS STRING) shape, region FROM "geo" ORDER BY "city"; city:s | location:s | location_no_dv:s | geoshape:s | shape:s | region:s -Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |POINT (4.850312 52.347557 2.0) |Europe -Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |POINT (13.390889 52.486701 34.0) |Europe -Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |POINT (-87.637874 41.888783 181.0) |Americas -Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |POINT (114.183925 22.281397 552.0) |Asia -London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |POINT (-0.121672 51.510871 11.0) |Europe -Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |POINT (-122.083843 37.386483 30.0) |Americas -Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |POINT (11.537505 48.146321 519.0) |Europe -New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |POINT (-73.990027 40.745171 10.0) |Americas -Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |POINT (2.351773 48.845538 35.0) |Europe -Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|POINT (-111.973505 33.376242 331.0)|Americas -San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |POINT (-122.394228 37.789541 16.0) |Americas -Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |POINT (127.060851 37.509132 38.0) |Asia -Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |POINT (103.855535 1.295868 15.0) |Asia -Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|POINT (151.208629 -33.863385 100.0)|Asia -Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|POINT (139.76402225 35.669616 40.0)|Asia +Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |POINT (4.850312 52.347557 2.0) |Europe +Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |POINT (13.390889 52.486701 34.0) |Europe +Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |POINT (-87.637874 41.888783 181.0) |Americas +Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |POINT (114.183925 22.281397 552.0) |Asia +London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |POINT (-0.121672 51.510871 11.0) |Europe +Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |POINT (-122.083843 37.386483 30.0) |Americas +Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |POINT (11.537505 48.146321 519.0) |Europe +New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |POINT (-73.990027 40.745171 10.0) |Americas +Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |POINT (2.351773 48.845538 35.0) |Europe +Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|POINT (-111.973505 33.376242 331.0)|Americas +San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |POINT (-122.394228 37.789541 16.0) |Americas +Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |POINT (127.060851 37.509132 38.0) |Asia +Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |POINT (103.855535 1.295868 15.0) |Asia +Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|POINT (151.208629 -33.863385 100.0)|Asia +Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|POINT (139.76402225 35.669616 40.0)|Asia ; // TODO: Both shape and location contain the same data for now, we should change it later to make things more interesting @@ -55,49 +55,49 @@ selectAllPointsAsWKT SELECT city, ST_ASWKT(location) location_wkt, ST_ASWKT(geoshape) geoshape_wkt, region FROM "geo" ORDER BY "city"; city:s | location_wkt:s | geoshape_wkt:s | region:s -Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |Europe -Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |Europe -Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |Americas -Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |Asia -London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |Europe -Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |Americas -Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |Europe -New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |Americas -Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |Europe -Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|Americas -San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |Americas -Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |Asia -Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |Asia -Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|Asia -Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|Asia +Amsterdam |POINT (4.850312 52.347557) |POINT (4.850312 52.347557 2.0) |Europe +Berlin |POINT (13.390889 52.486701) |POINT (13.390889 52.486701 34.0) |Europe +Chicago |POINT (-87.637874 41.888783) |POINT (-87.637874 41.888783 181.0) |Americas +Hong Kong |POINT (114.183925 22.281397) |POINT (114.183925 22.281397 552.0) |Asia +London |POINT (-0.121672 51.510871) |POINT (-0.121672 51.510871 11.0) |Europe +Mountain View |POINT (-122.083843 37.386483) |POINT (-122.083843 37.386483 30.0) |Americas +Munich |POINT (11.537505 48.146321) |POINT (11.537505 48.146321 519.0) |Europe +New York |POINT (-73.990027 40.745171) |POINT (-73.990027 40.745171 10.0) |Americas +Paris |POINT (2.351773 48.845538) |POINT (2.351773 48.845538 35.0) |Europe +Phoenix |POINT (-111.973505 33.376242) |POINT (-111.973505 33.376242 331.0)|Americas +San Francisco |POINT (-122.394228 37.789541) |POINT (-122.394228 37.789541 16.0) |Americas +Seoul |POINT (127.060851 37.509132) |POINT (127.060851 37.509132 38.0) |Asia +Singapore |POINT (103.855535 1.295868) |POINT (103.855535 1.295868 15.0) |Asia +Sydney |POINT (151.208629 -33.863385) |POINT (151.208629 -33.863385 100.0)|Asia +Tokyo |POINT (139.76402225 35.669616)|POINT (139.76402225 35.669616 40.0)|Asia ; selectWithAsWKTInWhere SELECT city, ST_ASWKT(location) location_wkt, region FROM "geo" WHERE LOCATE('114', ST_ASWKT(location)) > 0 ORDER BY "city"; city:s | location_wkt:s | region:s -Hong Kong |POINT (114.183925 22.281397)|Asia +Hong Kong |POINT (114.183925 22.281397)|Asia ; selectAllPointsOrderByLonFromAsWKT SELECT city, SUBSTRING(ST_ASWKT(location), 8, LOCATE(' ', ST_ASWKT(location), 8) - 8) lon FROM "geo" ORDER BY lon; city:s | lon:s -London |-0.121672 -Phoenix |-111.973505 -Mountain View |-122.083843 -San Francisco |-122.394228 -New York |-73.990027 -Chicago |-87.637874 -Singapore |103.855535 -Munich |11.537505 -Hong Kong |114.183925 -Seoul |127.060851 -Berlin |13.390889 -Tokyo |139.76402225 -Sydney |151.208629 -Paris |2.351773 -Amsterdam |4.850312 +London |-0.121672 +Phoenix |-111.973505 +Mountain View |-122.083843 +San Francisco |-122.394228 +New York |-73.990027 +Chicago |-87.637874 +Singapore |103.855535 +Munich |11.537505 +Hong Kong |114.183925 +Seoul |127.060851 +Berlin |13.390889 +Tokyo |139.76402225 +Sydney |151.208629 +Paris |2.351773 +Amsterdam |4.850312 ; selectAllPointsGroupByHemisphereFromAsWKT @@ -158,8 +158,8 @@ SELECT region, city, ST_Distance(location, ST_WktToSQL('POINT (-71 42)')) distan region:s | city:s | distance:d Americas |Chicago |1373941.5075370357 -Americas |Mountain View |4335936.907008218 -Americas |New York |285839.6512191343 +Americas |Mountain View |4335936.907008218 +Americas |New York |285839.6512191343 Americas |Phoenix |3692895.0329883597 Americas |San Francisco |4343565.009715615 ; @@ -268,14 +268,14 @@ selectFilterByXOfLocation SELECT city, ST_X(geoshape) x, ST_Y(geoshape) y, ST_Z(geoshape) z, ST_X(location) lx, ST_Y(location) ly FROM geo WHERE lx > 0 ORDER BY ly; city:s | x:d | y:d | z:d | lx:d | ly:d -Sydney |151.208629 |-33.863385 |100.0 |151.208629 |-33.863385 -Singapore |103.855535 |1.295868 |15.0 |103.855535 |1.295868 -Hong Kong |114.183925 |22.281397 |552.0 |114.183925 |22.281397 -Tokyo |139.76402225 |35.669616 |40.0 |139.76402225 |35.669616 -Seoul |127.060851 |37.509132 |38.0 |127.060851 |37.509132 -Munich |11.537505 |48.146321 |519.0 |11.537505 |48.146321 -Paris |2.351773 |48.845538 |35.0 |2.351773 |48.845538 -Amsterdam |4.850312 |52.347557 |2.0 |4.850312 |52.347557 +Sydney |151.208629 |-33.863385 |100.0 |151.208629 |-33.863385 +Singapore |103.855535 |1.295868 |15.0 |103.855535 |1.295868 +Hong Kong |114.183925 |22.281397 |552.0 |114.183925 |22.281397 +Tokyo |139.76402225 |35.669616 |40.0 |139.76402225 |35.669616 +Seoul |127.060851 |37.509132 |38.0 |127.060851 |37.509132 +Munich |11.537505 |48.146321 |519.0 |11.537505 |48.146321 +Paris |2.351773 |48.845538 |35.0 |2.351773 |48.845538 +Amsterdam |4.850312 |52.347557 |2.0 |4.850312 |52.347557 Berlin |13.390889 |52.486701 |34.0 |13.390889 |52.486701 ; @@ -283,10 +283,10 @@ selectFilterByRegionPoint SELECT city, region, ST_X(location) x FROM geo WHERE ST_X(ST_WKTTOSQL(region_point)) < 0 ORDER BY x; city:s | region:s | x:d -San Francisco |Americas |-122.394228 -Mountain View |Americas |-122.083843 -Phoenix |Americas |-111.973505 -Chicago |Americas |-87.637874 +San Francisco |Americas |-122.394228 +Mountain View |Americas |-122.083843 +Phoenix |Americas |-111.973505 +Chicago |Americas |-87.637874 New York |Americas |-73.990027 ; diff --git a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 index 0e9dc2a5aae16..d2e925b2fa5d3 100644 --- a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 +++ b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 @@ -70,7 +70,7 @@ statement (columnPattern=likePattern)? #sysColumns | SYS TYPES ((PLUS | MINUS)? type=number)? #sysTypes ; - + query : (WITH namedQuery (',' namedQuery)*)? queryNoWith ; @@ -83,10 +83,10 @@ queryNoWith ; limitClause - : LIMIT limit=(INTEGER_VALUE | ALL) - | LIMIT_ESC limit=(INTEGER_VALUE | ALL) ESC_END + : LIMIT limit=(INTEGER_VALUE | ALL) + | LIMIT_ESC limit=(INTEGER_VALUE | ALL) ESC_END ; - + queryTerm : querySpecification #queryPrimaryDefault | '(' queryNoWith ')' #subquery @@ -134,7 +134,7 @@ setQuantifier | ALL ; -selectItems +selectItems : selectItem (',' selectItem)* ; @@ -174,13 +174,13 @@ pivotClause ; pivotArgs - : namedValueExpression (',' namedValueExpression)* + : namedValueExpression (',' namedValueExpression)* ; - + namedValueExpression : valueExpression (AS? identifier)? ; - + expression : booleanExpression ; @@ -221,11 +221,11 @@ predicate likePattern : LIKE pattern ; - + pattern : value=string patternEscape? ; - + patternEscape : ESCAPE escape=string | ESCAPE_ESC escape=string ESC_END @@ -278,7 +278,7 @@ extractExpression : extractTemplate | FUNCTION_ESC extractTemplate ESC_END ; - + extractTemplate : EXTRACT '(' field=identifier FROM valueExpression ')' ; @@ -287,16 +287,16 @@ functionExpression : functionTemplate | FUNCTION_ESC functionTemplate ESC_END ; - + functionTemplate : functionName '(' (setQuantifier? expression (',' expression)*)? ')' ; functionName - : LEFT - | RIGHT + : LEFT + | RIGHT | identifier ; - + constant : NULL #nullLiteral | interval #intervalLiteral @@ -319,9 +319,9 @@ booleanValue ; interval - : INTERVAL sign=(PLUS | MINUS)? (valueNumeric=number | valuePattern=string) leading=intervalField (TO trailing=intervalField)? + : INTERVAL sign=(PLUS | MINUS)? (valueNumeric=number | valuePattern=string) leading=intervalField (TO trailing=intervalField)? ; - + intervalField : YEAR | YEARS | MONTH | MONTHS | DAY | DAYS | HOUR | HOURS | MINUTE | MINUTES | SECOND | SECONDS ; @@ -372,19 +372,19 @@ whenClause // http://developer.mimer.se/validator/sql-reserved-words.tml // https://developer.mimer.com/wp-content/uploads/standard-sql-reserved-words-summary.pdf nonReserved - : ANALYZE | ANALYZED + : ANALYZE | ANALYZED | CATALOGS | COLUMNS | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP - | DAY | DEBUG - | EXECUTABLE | EXPLAIN + | DAY | DEBUG + | EXECUTABLE | EXPLAIN | FIRST | FORMAT | FULL | FUNCTIONS | GRAPHVIZ | HOUR | INTERVAL - | LAST | LIMIT + | LAST | LIMIT | MAPPED | MINUTE | MONTH - | OPTIMIZED - | PARSED | PHYSICAL | PIVOT | PLAN - | QUERY + | OPTIMIZED + | PARSED | PHYSICAL | PIVOT | PLAN + | QUERY | RLIKE | SCHEMAS | SECOND | SHOW | SYS | TABLES | TEXT | TOP | TYPE | TYPES diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java index 1f7eaa7c33ccc..d44723b6b0539 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowCatalogs.java @@ -1,7 +1,8 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. + * 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.sql.plan.logical.command; From b6cf6782a4f858fd00ac4b1563c3ca78733cf740 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Mon, 11 Oct 2021 14:15:06 +0200 Subject: [PATCH 03/12] Add metadata test and fix expected output of other Add getClusters() metadata test. Adjust expected output of other 'SHOW TABLES' tests. --- .../multi-cluster-with-security/build.gradle | 1 - .../JdbcMetadataIT.java | 33 +++++++++++++++++++ .../xpack/sql/qa/security/CliSecurityIT.java | 5 +-- .../sql/qa/security/RestSqlSecurityIT.java | 4 ++- 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle index 675b29a9aa31a..c79ef7fbde906 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle @@ -10,7 +10,6 @@ dependencies { def remoteClusterReg = testClusters.register('remote-cluster') { testDistribution = 'DEFAULT' - // numberOfNodes = 2 setting 'node.roles', '[data,ingest,master]' setting 'xpack.ml.enabled', 'false' setting 'xpack.watcher.enabled', 'false' diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java new file mode 100644 index 0000000000000..c593ea612f6b6 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java @@ -0,0 +1,33 @@ +/* + * 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.sql.qa.multi_cluster_with_security; + +import org.elasticsearch.xpack.sql.qa.jdbc.JdbcIntegrationTestCase; + +import java.sql.Connection; +import java.sql.ResultSet; + +public class JdbcMetadataIT extends JdbcIntegrationTestCase { + + // gradle defines + public static final String LOCAL_CLUSTER_NAME = "integTest"; + public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; + + @AwaitsFix(bugUrl = "foo") + public void testJdbcGetClusters() throws Exception { + try (Connection es = esJdbc()) { + ResultSet rs = es.getMetaData().getCatalogs(); + assertEquals(1, rs.getMetaData().getColumnCount()); + assertTrue(rs.next()); + assertEquals(LOCAL_CLUSTER_NAME, rs.getString(1)); + assertTrue(rs.next()); + assertEquals(REMOTE_CLUSTER_NAME, rs.getString(1)); + assertFalse(rs.next()); + } + } +} diff --git a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliSecurityIT.java b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliSecurityIT.java index 35aa0f2e048c5..4fb5143860380 100644 --- a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliSecurityIT.java +++ b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliSecurityIT.java @@ -165,10 +165,11 @@ public void expectDescribe(Map> columns, String user) throw public void expectShowTables(List tables, String user) throws Exception { try (EmbeddedCli cli = new EmbeddedCli(elasticsearchAddress(), true, userSecurity(user))) { String tablesOutput = cli.command("SHOW TABLES"); + assertThat(tablesOutput, containsString("catalog")); assertThat(tablesOutput, containsString("name")); assertThat(tablesOutput, containsString("type")); assertThat(tablesOutput, containsString("kind")); - assertEquals("---------------+---------------+---------------", cli.readLine()); + assertEquals("---------------+---------------+---------------+---------------", cli.readLine()); for (String table : tables) { String line = null; /* @@ -176,7 +177,7 @@ public void expectShowTables(List tables, String user) throws Exception * `.security6` index but it might not have created the index * by the time the test runs. */ - while (line == null || line.startsWith(".security")) { + while (line == null || line.contains("|.security")) { line = cli.readLine(); } assertThat(line, containsString(table)); diff --git a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/RestSqlSecurityIT.java b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/RestSqlSecurityIT.java index f094950f6f3f5..a559670b709ad 100644 --- a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/RestSqlSecurityIT.java +++ b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/RestSqlSecurityIT.java @@ -143,6 +143,7 @@ public void expectDescribe(Map> columns, String user) throw public void expectShowTables(List tables, String user) throws Exception { String mode = randomMode(); List columns = new ArrayList<>(); + columns.add(columnInfo(mode, "catalog", "keyword", JDBCType.VARCHAR, 32766)); columns.add(columnInfo(mode, "name", "keyword", JDBCType.VARCHAR, 32766)); columns.add(columnInfo(mode, "type", "keyword", JDBCType.VARCHAR, 32766)); columns.add(columnInfo(mode, "kind", "keyword", JDBCType.VARCHAR, 32766)); @@ -151,6 +152,7 @@ public void expectShowTables(List tables, String user) throws Exception List> rows = new ArrayList<>(); for (String table : tables) { List fields = new ArrayList<>(); + fields.add("integTest"); // gradle defined fields.add(table); fields.add("TABLE"); fields.add("INDEX"); @@ -167,7 +169,7 @@ public void expectShowTables(List tables, String user) throws Exception */ @SuppressWarnings("unchecked") List> rowsNoSecurity = ((List>) actual.get("rows")).stream() - .filter(ls -> ls.get(0).startsWith(".security") == false) + .filter(ls -> ls.get(1).startsWith(".security") == false) .collect(Collectors.toList()); actual.put("rows", rowsNoSecurity); assertResponse(expected, actual); From 27654142019dad5993a30ca21b49567c9ebfe657 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Thu, 14 Oct 2021 10:46:43 +0200 Subject: [PATCH 04/12] Address review comment Extract RemoteClusterResolver into own class and ony pass a supplier of remote clusters to the IndexResolver. --- .../xpack/eql/plugin/EqlPlugin.java | 6 ++- .../xpack/eql/analysis/CancellationTests.java | 5 +-- .../xpack/ql/index/IndexResolver.java | 34 +++------------- .../xpack/ql/index/RemoteClusterResolver.java | 40 +++++++++++++++++++ .../JdbcMetadataIT.java | 4 +- .../xpack/sql/plugin/SqlPlugin.java | 6 ++- .../xpack/sql/analysis/CancellationTests.java | 5 +-- 7 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/RemoteClusterResolver.java diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java index 044ce3702820b..08f48ec06bb46 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/EqlPlugin.java @@ -43,6 +43,7 @@ import org.elasticsearch.xpack.eql.action.EqlSearchAction; import org.elasticsearch.xpack.eql.execution.PlanExecutor; import org.elasticsearch.xpack.ql.index.IndexResolver; +import org.elasticsearch.xpack.ql.index.RemoteClusterResolver; import org.elasticsearch.xpack.ql.type.DefaultDataTypeRegistry; import java.util.Collection; import java.util.Collections; @@ -75,8 +76,9 @@ public Collection createComponents(Client client, ClusterService cluster } private Collection createComponents(Client client, Settings settings, ClusterService clusterService) { - IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), settings, - clusterService.getClusterSettings(), DefaultDataTypeRegistry.INSTANCE); + RemoteClusterResolver remoteClusterResolver = new RemoteClusterResolver(settings, clusterService.getClusterSettings()); + IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), DefaultDataTypeRegistry.INSTANCE, + remoteClusterResolver::remoteClusters); PlanExecutor planExecutor = new PlanExecutor(client, indexResolver, circuitBreaker.get()); return Collections.singletonList(planExecutor); } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java index 589438f992f4e..835dde846b304 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/CancellationTests.java @@ -20,7 +20,6 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.breaker.NoopCircuitBreaker; -import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.TaskCancelHelper; import org.elasticsearch.tasks.TaskCancelledException; @@ -43,6 +42,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -245,7 +245,6 @@ private ClusterService mockClusterService(String nodeId) { } private static IndexResolver indexResolver(Client client) { - return new IndexResolver(client, randomAlphaOfLength(10), Settings.EMPTY, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), DefaultDataTypeRegistry.INSTANCE); + return new IndexResolver(client, randomAlphaOfLength(10), DefaultDataTypeRegistry.INSTANCE, Collections::emptySet); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java index cf00f483062a6..1f132b3954e86 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java @@ -23,13 +23,9 @@ import org.elasticsearch.cluster.metadata.AliasMetadata; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableOpenMap; -import org.elasticsearch.common.settings.ClusterSettings; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.Tuple; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.transport.NoSuchRemoteClusterException; -import org.elasticsearch.transport.RemoteClusterAware; -import org.elasticsearch.transport.RemoteConnectionStrategy; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataTypeRegistry; @@ -59,9 +55,9 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.function.Supplier; import java.util.regex.Pattern; import static java.util.Arrays.asList; @@ -180,14 +176,13 @@ public boolean equals(Object obj) { private final String clusterName; private final DataTypeRegistry typeRegistry; - private final RemoteClusterResolver remoteClusters; + private final Supplier> remoteClusters; - public IndexResolver(Client client, String clusterName, Settings settings, ClusterSettings clusterSettings, - DataTypeRegistry typeRegistry) { + public IndexResolver(Client client, String clusterName, DataTypeRegistry typeRegistry, Supplier> remoteClusters) { this.client = client; this.clusterName = clusterName; this.typeRegistry = typeRegistry; - this.remoteClusters = new RemoteClusterResolver(settings, clusterSettings); + this.remoteClusters = remoteClusters; } public String clusterName() { @@ -195,7 +190,7 @@ public String clusterName() { } public Set remoteClusters() { - return new TreeSet<>(remoteClusters.clusters); + return remoteClusters.get(); } /** @@ -857,23 +852,4 @@ private static Map getInvalidFieldsForAliases(String // everything checks return emptyMap(); } - - private static class RemoteClusterResolver extends RemoteClusterAware { - private final CopyOnWriteArraySet clusters; - - private RemoteClusterResolver(Settings settings, ClusterSettings clusterSettings) { - super(settings); - clusters = new CopyOnWriteArraySet<>(getEnabledRemoteClusters(settings)); - listenForUpdates(clusterSettings); - } - - @Override - protected void updateRemoteCluster(String clusterAlias, Settings settings) { - if (RemoteConnectionStrategy.isConnectionEnabled(clusterAlias, settings)) { - clusters.add(clusterAlias); - } else { - clusters.remove(clusterAlias); - } - } - } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/RemoteClusterResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/RemoteClusterResolver.java new file mode 100644 index 0000000000000..d7db72808c940 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/RemoteClusterResolver.java @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.ql.index; + +import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.transport.RemoteClusterAware; +import org.elasticsearch.transport.RemoteConnectionStrategy; + +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.CopyOnWriteArraySet; + +public class RemoteClusterResolver extends RemoteClusterAware { + private final CopyOnWriteArraySet clusters; + + public RemoteClusterResolver(Settings settings, ClusterSettings clusterSettings) { + super(settings); + clusters = new CopyOnWriteArraySet<>(getEnabledRemoteClusters(settings)); + listenForUpdates(clusterSettings); + } + + @Override + protected void updateRemoteCluster(String clusterAlias, Settings settings) { + if (RemoteConnectionStrategy.isConnectionEnabled(clusterAlias, settings)) { + clusters.add(clusterAlias); + } else { + clusters.remove(clusterAlias); + } + } + + public Set remoteClusters() { + return new TreeSet<>(clusters); + } +} diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java index c593ea612f6b6..203e1928ff73e 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcMetadataIT.java @@ -11,6 +11,7 @@ import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; public class JdbcMetadataIT extends JdbcIntegrationTestCase { @@ -18,8 +19,7 @@ public class JdbcMetadataIT extends JdbcIntegrationTestCase { public static final String LOCAL_CLUSTER_NAME = "integTest"; public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; - @AwaitsFix(bugUrl = "foo") - public void testJdbcGetClusters() throws Exception { + public void testJdbcGetClusters() throws SQLException { try (Connection es = esJdbc()) { ResultSet rs = es.getMetaData().getCatalogs(); assertEquals(1, rs.getMetaData().getColumnCount()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java index fc5350dcb9e1d..25cdc29ac82b5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java @@ -36,6 +36,7 @@ import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction; import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction; import org.elasticsearch.xpack.ql.index.IndexResolver; +import org.elasticsearch.xpack.ql.index.RemoteClusterResolver; import org.elasticsearch.xpack.sql.SqlInfoTransportAction; import org.elasticsearch.xpack.sql.SqlUsageTransportAction; import org.elasticsearch.xpack.sql.action.SqlClearCursorAction; @@ -99,8 +100,9 @@ public Collection createComponents(Client client, ClusterService cluster */ Collection createComponents(Client client, Settings settings, ClusterService clusterService, NamedWriteableRegistry namedWriteableRegistry) { - IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), settings, - clusterService.getClusterSettings(), SqlDataTypeRegistry.INSTANCE); + RemoteClusterResolver remoteClusterResolver = new RemoteClusterResolver(settings, clusterService.getClusterSettings()); + IndexResolver indexResolver = new IndexResolver(client, clusterService.getClusterName().value(), SqlDataTypeRegistry.INSTANCE, + remoteClusterResolver::remoteClusters); return Arrays.asList(sqlLicenseChecker, indexResolver, new PlanExecutor(client, indexResolver, namedWriteableRegistry)); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java index 9b87b14361e45..3a04a064cef23 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/CancellationTests.java @@ -18,8 +18,6 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.settings.ClusterSettings; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.TaskCancelHelper; import org.elasticsearch.tasks.TaskCancelledException; import org.elasticsearch.tasks.TaskId; @@ -225,8 +223,7 @@ private ClusterService mockClusterService(String nodeId) { } private static IndexResolver indexResolver(Client client) { - return new IndexResolver(client, randomAlphaOfLength(10), Settings.EMPTY, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), DefaultDataTypeRegistry.INSTANCE); + return new IndexResolver(client, randomAlphaOfLength(10), DefaultDataTypeRegistry.INSTANCE, Collections::emptySet); } private static SqlQueryTask randomTask() { From 2ee6bf997a957964fcd58fd13b5f3765514a57bd Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Thu, 14 Oct 2021 11:07:13 +0200 Subject: [PATCH 05/12] Add a "catalog" request parameter. This adds a new "catalog" request parameter, to be used by the xDBC clients. It's value is whatever the set-catalog xDBC action is passed to by the application and will have ES/SQL run the query on the indicated cluster, in case the query itself doesn't spacify a cluster target (which takes precedence over the parameter). --- .../xpack/sql/jdbc/JdbcConfiguration.java | 18 ++-- .../xpack/sql/jdbc/JdbcConnection.java | 11 ++- .../xpack/sql/jdbc/JdbcHttpClient.java | 11 ++- .../xpack/sql/jdbc/JdbcPreparedStatement.java | 4 +- .../xpack/sql/jdbc/JdbcStatement.java | 6 +- .../sql/jdbc/JdbcHttpClientRequestTests.java | 2 +- .../sql/jdbc/JdbcPreparedStatementTests.java | 2 +- .../xpack/sql/jdbc/VersionParityTests.java | 5 +- .../JdbcCatalogIT.java | 86 +++++++++++++++++++ .../JdbcCsvSpecIT.java | 19 +++- .../sql/qa/rest/BaseRestSqlTestCase.java | 6 ++ .../sql/action/AbstractSqlQueryRequest.java | 26 +++++- .../xpack/sql/action/SqlQueryRequest.java | 6 +- .../sql/action/SqlQueryRequestBuilder.java | 15 ++-- .../xpack/sql/action/SqlTranslateRequest.java | 4 +- .../sql/action/SqlQueryRequestTests.java | 13 ++- .../sql/action/SqlTranslateRequestTests.java | 1 + .../sql/client/ConnectionConfiguration.java | 6 +- .../xpack/sql/client/HttpClient.java | 2 +- .../sql/client/HttpClientRequestTests.java | 1 + .../xpack/sql/proto/Protocol.java | 1 + .../xpack/sql/proto/SqlQueryRequest.java | 25 ++++-- .../xpack/sql/analysis/analyzer/Analyzer.java | 2 +- .../sql/plan/logical/command/ShowColumns.java | 5 +- .../sql/plan/logical/command/ShowTables.java | 2 + .../plugin/TransportSqlClearCursorAction.java | 2 +- .../sql/plugin/TransportSqlQueryAction.java | 6 +- .../plugin/TransportSqlTranslateAction.java | 2 +- .../xpack/sql/session/SqlConfiguration.java | 15 +++- .../xpack/sql/session/SqlSession.java | 5 +- .../elasticsearch/xpack/sql/SqlTestUtils.java | 3 +- .../scalar/DatabaseFunctionTests.java | 2 +- .../function/scalar/UserFunctionTests.java | 2 +- .../logical/command/sys/SysColumnsTests.java | 4 +- .../logical/command/sys/SysTablesTests.java | 2 +- .../logical/command/sys/SysTypesTests.java | 2 +- .../sql/plugin/SqlMediaTypeParserTests.java | 2 +- 37 files changed, 256 insertions(+), 70 deletions(-) create mode 100644 x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConfiguration.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConfiguration.java index 209fe2c9a9205..262e3dee195b5 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConfiguration.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConfiguration.java @@ -62,6 +62,8 @@ public class JdbcConfiguration extends ConnectionConfiguration { // really, the way to move forward is to specify a calendar or the timezone manually static final String TIME_ZONE_DEFAULT = TimeZone.getDefault().getID(); + public static final String CATALOG = "catalog"; + static final String FIELD_MULTI_VALUE_LENIENCY = "field.multi.value.leniency"; static final String FIELD_MULTI_VALUE_LENIENCY_DEFAULT = "true"; @@ -71,7 +73,7 @@ public class JdbcConfiguration extends ConnectionConfiguration { // options that don't change at runtime private static final Set OPTION_NAMES = new LinkedHashSet<>( - Arrays.asList(TIME_ZONE, FIELD_MULTI_VALUE_LENIENCY, INDEX_INCLUDE_FROZEN, DEBUG, DEBUG_OUTPUT, DEBUG_FLUSH_ALWAYS)); + Arrays.asList(TIME_ZONE, CATALOG, FIELD_MULTI_VALUE_LENIENCY, INDEX_INCLUDE_FROZEN, DEBUG, DEBUG_OUTPUT, DEBUG_FLUSH_ALWAYS)); static { // trigger version initialization @@ -81,15 +83,14 @@ public class JdbcConfiguration extends ConnectionConfiguration { ClientVersion.CURRENT.toString(); } - // immutable properties private final boolean debug; private final String debugOut; private final boolean flushAlways; - // mutable ones - private ZoneId zoneId; - private boolean fieldMultiValueLeniency; - private boolean includeFrozen; + private final ZoneId zoneId; + private final String catalog; + private final boolean fieldMultiValueLeniency; + private final boolean includeFrozen; public static JdbcConfiguration create(String u, Properties props, int loginTimeoutSeconds) throws JdbcSQLException { URI uri = parseUrl(u); @@ -175,6 +176,7 @@ private JdbcConfiguration(URI baseURI, String u, Properties props) throws JdbcSQ this.zoneId = parseValue(TIME_ZONE, props.getProperty(TIME_ZONE, TIME_ZONE_DEFAULT), s -> TimeZone.getTimeZone(s).toZoneId().normalized()); + this.catalog = props.getProperty(CATALOG); this.fieldMultiValueLeniency = parseValue(FIELD_MULTI_VALUE_LENIENCY, props.getProperty(FIELD_MULTI_VALUE_LENIENCY, FIELD_MULTI_VALUE_LENIENCY_DEFAULT), Boolean::parseBoolean); this.includeFrozen = parseValue(INDEX_INCLUDE_FROZEN, props.getProperty(INDEX_INCLUDE_FROZEN, INDEX_INCLUDE_FROZEN_DEFAULT), @@ -206,6 +208,10 @@ public TimeZone timeZone() { return zoneId != null ? TimeZone.getTimeZone(zoneId) : null; } + String catalog() { + return catalog; + } + public boolean fieldMultiValueLeniency() { return fieldMultiValueLeniency; } diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConnection.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConnection.java index ecc937c16e8ac..818f631da9557 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConnection.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcConnection.java @@ -51,7 +51,8 @@ class JdbcConnection implements Connection, JdbcWrapper { JdbcConnection(JdbcConfiguration connectionInfo, boolean checkServer) throws SQLException { cfg = connectionInfo; - client = new JdbcHttpClient(connectionInfo, checkServer); + client = new JdbcHttpClient(this, checkServer); + catalog = cfg.catalog(); url = connectionInfo.connectionString(); userName = connectionInfo.authUser(); } @@ -65,13 +66,13 @@ private void checkOpen() throws SQLException { @Override public Statement createStatement() throws SQLException { checkOpen(); - return new JdbcStatement(this, cfg); + return new JdbcStatement(this); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { checkOpen(); - return new JdbcPreparedStatement(this, cfg, sql); + return new JdbcPreparedStatement(this, sql); } @Override @@ -414,6 +415,10 @@ private void checkHoldability(int resultSetHoldability) throws SQLException { } } + JdbcConfiguration config() { + return cfg; + } + String getURL() { return url; } diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java index 1f5e36ea26d29..15765a8e45f22 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java @@ -32,6 +32,7 @@ */ class JdbcHttpClient { private final HttpClient httpClient; + private final JdbcConnection jdbcConn; private final JdbcConfiguration conCfg; private InfoResponse serverInfo; @@ -39,13 +40,14 @@ class JdbcHttpClient { * The SQLException is the only type of Exception the JDBC API can throw (and that the user expects). * If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown */ - JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException { - this(conCfg, true); + JdbcHttpClient(JdbcConnection jdbcConn) throws SQLException { + this(jdbcConn, true); } - JdbcHttpClient(JdbcConfiguration conCfg, boolean checkServer) throws SQLException { + JdbcHttpClient(JdbcConnection jdbcConn, boolean checkServer) throws SQLException { + this.jdbcConn = jdbcConn; + conCfg = jdbcConn.config(); httpClient = new HttpClient(conCfg); - this.conCfg = conCfg; if (checkServer) { this.serverInfo = fetchServerInfo(); checkServerVersion(); @@ -59,6 +61,7 @@ boolean ping(long timeoutInMs) throws SQLException { Cursor query(String sql, List params, RequestMeta meta) throws SQLException { int fetch = meta.fetchSize() > 0 ? meta.fetchSize() : conCfg.pageSize(); SqlQueryRequest sqlRequest = new SqlQueryRequest(sql, params, conCfg.zoneId(), + jdbcConn.getCatalog(), fetch, TimeValue.timeValueMillis(meta.timeoutInMs()), TimeValue.timeValueMillis(meta.queryTimeoutInMs()), diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatement.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatement.java index 81b57ccd86dec..3f087c608a47c 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatement.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatement.java @@ -49,8 +49,8 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement { final PreparedQuery query; - JdbcPreparedStatement(JdbcConnection con, JdbcConfiguration info, String sql) throws SQLException { - super(con, info); + JdbcPreparedStatement(JdbcConnection con, String sql) throws SQLException { + super(con); this.query = PreparedQuery.prepare(sql); } diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcStatement.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcStatement.java index b66d661b05e70..f85964614bc6b 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcStatement.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcStatement.java @@ -30,10 +30,10 @@ class JdbcStatement implements Statement, JdbcWrapper { protected JdbcResultSet rs; final RequestMeta requestMeta; - JdbcStatement(JdbcConnection jdbcConnection, JdbcConfiguration info) { + JdbcStatement(JdbcConnection jdbcConnection) { this.con = jdbcConnection; - this.cfg = info; - this.requestMeta = new RequestMeta(info.pageSize(), info.pageTimeout(), info.queryTimeout()); + this.cfg = con.config(); + this.requestMeta = new RequestMeta(cfg.pageSize(), cfg.pageTimeout(), cfg.queryTimeout()); } @Override diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java index d22f90d88e322..1dd0d99c9659e 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java @@ -74,7 +74,7 @@ private void assertBinaryRequest(boolean isBinary, XContentType xContentType) th Properties props = new Properties(); props.setProperty(ConnectionConfiguration.BINARY_COMMUNICATION, Boolean.toString(isBinary)); - JdbcHttpClient httpClient = new JdbcHttpClient(JdbcConfiguration.create(url, props, 0), false); + JdbcHttpClient httpClient = new JdbcHttpClient(new JdbcConnection(JdbcConfiguration.create(url, props, 0), false), false); prepareMockResponse(); try { diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatementTests.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatementTests.java index 440c167cfcc35..31e17ecac19cb 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatementTests.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcPreparedStatementTests.java @@ -586,7 +586,7 @@ public void testThrownExceptionsWhenSettingByteArrayValuesToEsTypes() throws SQL } private JdbcPreparedStatement createJdbcPreparedStatement() throws SQLException { - return new JdbcPreparedStatement(null, JdbcConfiguration.create("jdbc:es://l:1", null, 0), "?"); + return new JdbcPreparedStatement(new JdbcConnection(JdbcConfiguration.create("jdbc:es://l:1", null, 0), false), "?"); } private EsType jdbcType(JdbcPreparedStatement jps) throws SQLException { diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/VersionParityTests.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/VersionParityTests.java index b6212745c4415..2657aa8d2f34a 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/VersionParityTests.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/VersionParityTests.java @@ -39,7 +39,8 @@ public void testExceptionThrownOnIncompatibleVersions() throws IOException, SQLE // Client's version is wired up to patch level, excluding the qualifier => generate the test version as the server does it. String versionString = SqlVersion.fromString(version.toString()).toString(); - SQLException ex = expectThrows(SQLException.class, () -> new JdbcHttpClient(JdbcConfiguration.create(url, null, 0))); + SQLException ex = expectThrows(SQLException.class, () -> new JdbcHttpClient(new JdbcConnection( + JdbcConfiguration.create(url, null, 0), false))); assertEquals("This version of the JDBC driver is only compatible with Elasticsearch version " + ClientVersion.CURRENT.majorMinorToString() + " or newer; attempting to connect to a server " + "version " + versionString, ex.getMessage()); @@ -52,7 +53,7 @@ public void testNoExceptionThrownForCompatibleVersions() throws IOException { try { do { prepareResponse(version); - new JdbcHttpClient(JdbcConfiguration.create(url, null, 0)); + new JdbcHttpClient(new JdbcConnection(JdbcConfiguration.create(url, null, 0), false)); version = VersionUtils.getPreviousVersion(version); } while (version.compareTo(Version.V_7_7_0) >= 0); } catch (SQLException sqle) { diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java new file mode 100644 index 0000000000000..6302da15e6d69 --- /dev/null +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java @@ -0,0 +1,86 @@ +/* + * 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.sql.qa.multi_cluster_with_security; + +import org.elasticsearch.client.Request; +import org.elasticsearch.xpack.sql.qa.jdbc.JdbcIntegrationTestCase; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; + +public class JdbcCatalogIT extends JdbcIntegrationTestCase { + + // gradle defines + public static final String LOCAL_CLUSTER_NAME = "integTest"; + public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; + + private static final String INDEX_NAME = "test"; + + @BeforeClass + static void setupIndex() throws IOException { + index(INDEX_NAME, body -> body.field("zero", 0)); + } + + @AfterClass + static void cleanupIndex() throws IOException { + provisioningClient().performRequest(new Request("DELETE", "/" + INDEX_NAME)); + } + + public void testJdbcSetCatalog() throws Exception { + try (Connection es = esJdbc()) { + PreparedStatement ps = es.prepareStatement("SELECT count(*) FROM " + INDEX_NAME); + SQLException ex = expectThrows(SQLException.class, ps::executeQuery); + assertTrue(ex.getMessage().contains("Unknown index [" + INDEX_NAME + "]")); + + String catalog = REMOTE_CLUSTER_NAME.substring(0, randomIntBetween(0, REMOTE_CLUSTER_NAME.length())) + "*"; + es.setCatalog(catalog); + assertEquals(catalog, es.getCatalog()); + + ResultSet rs = ps.executeQuery(); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(1)); + assertFalse(rs.next()); + + es.setCatalog(LOCAL_CLUSTER_NAME); + expectThrows(SQLException.class, ps::executeQuery); + } + } + + public void testQueryCatalogPrecedence() throws Exception { + try (Connection es = esJdbc()) { + PreparedStatement ps = es.prepareStatement("SELECT count(*) FROM " + buildRemoteIndexName(REMOTE_CLUSTER_NAME, INDEX_NAME)); + es.setCatalog(LOCAL_CLUSTER_NAME); + ResultSet rs = ps.executeQuery(); + assertTrue(rs.next()); + assertFalse(rs.next()); + } + } + + public void testCatalogDependentCommands() throws Exception { + for (String query : List.of("SHOW TABLES", "SHOW COLUMNS FROM \"" + INDEX_NAME + "\"", "DESCRIBE \"" + INDEX_NAME + "\"")) { + try (Connection es = esJdbc()) { + PreparedStatement ps = es.prepareStatement(query); + ResultSet rs = ps.executeQuery(); + assertFalse(rs.next()); + + es.setCatalog(REMOTE_CLUSTER_NAME); + rs = ps.executeQuery(); + assertTrue(rs.next()); + assertFalse(rs.next()); + } + } + } +} diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java index 218a731fecc65..869bf66e5cc1f 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java @@ -11,9 +11,12 @@ import org.elasticsearch.xpack.sql.qa.jdbc.CsvSpecTestCase; import org.elasticsearch.xpack.sql.qa.jdbc.CsvTestUtils.CsvTestCase; +import java.sql.Connection; +import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.regex.Pattern; import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; import static org.elasticsearch.xpack.ql.TestUtils.classpathResources; @@ -24,6 +27,9 @@ public class JdbcCsvSpecIT extends CsvSpecTestCase { public static final String REMOTE_CLUSTER_NAME = "my_remote_cluster"; // gradle defined public static final String EXTRACT_FN_NAME = "EXTRACT"; + private static final Pattern DESCRIBE_OR_SHOW = Pattern.compile("(?i)\\s*(DESCRIBE|SHOW).*"); + private static final Pattern FROM_QUALIFIED = Pattern.compile("(?i)FROM\\w+" + REMOTE_CLUSTER_NAME + ":"); + @ParametersFactory(argumentFormatting = PARAM_FORMATTING) public static List readScriptSpec() throws Exception { List list = new ArrayList<>(); @@ -33,7 +39,7 @@ public static List readScriptSpec() throws Exception { } public JdbcCsvSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase) { - super(fileName, groupName, testName, lineNumber, qualifyFromClause(testCase)); + super(fileName, groupName, testName, lineNumber, randomBoolean() ? qualifyFromClause(testCase) : testCase); } // qualify the query FROM clause with the cluster name, but (crudely) skip `EXTRACT(a FROM b)` calls. @@ -84,10 +90,19 @@ private static CsvTestCase qualifyFromClause(CsvTestCase testCase) { } @Override + public Connection esJdbc() throws SQLException { + Connection connection = esJdbc(connectionProperties()); + if (FROM_QUALIFIED.matcher(csvTestCase().query).matches() == false) { + connection.setCatalog(REMOTE_CLUSTER_NAME); + } + return connection; + } + + @Override public boolean isEnabled() { return super.isEnabled() && // skip single-cluster tests that'd need a CLUSTER clause to work in multi-cluster mode. - (csvTestCase().query.matches("(?i)\\s*(DESCRIBE|SHOW).*") == false || fileName.startsWith("multi-cluster")); + (DESCRIBE_OR_SHOW.matcher(csvTestCase().query).matches() == false || fileName.startsWith("multi-cluster")); } diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java index 40a1ff7a7a05f..3ae1132fa7e3c 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/BaseRestSqlTestCase.java @@ -22,6 +22,7 @@ import java.util.Map; import static org.elasticsearch.xpack.sql.proto.Protocol.BINARY_FORMAT_NAME; +import static org.elasticsearch.xpack.sql.proto.Protocol.CATALOG_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CLIENT_ID_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.COLUMNAR_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CURSOR_NAME; @@ -86,6 +87,11 @@ public RequestObjectBuilder timeZone(String timeZone) { return this; } + public RequestObjectBuilder catalog(String catalog) { + request.append(field(CATALOG_NAME, catalog)); + return this; + } + public RequestObjectBuilder clientId(String clientId) { request.append(field(CLIENT_ID_NAME, clientId)); return this; diff --git a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/AbstractSqlQueryRequest.java b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/AbstractSqlQueryRequest.java index 4419ac230cd16..ff9749a0f74dd 100644 --- a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/AbstractSqlQueryRequest.java +++ b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/AbstractSqlQueryRequest.java @@ -43,6 +43,7 @@ import static java.util.Collections.emptyMap; import static org.elasticsearch.Version.CURRENT; import static org.elasticsearch.action.ValidateActions.addValidationError; +import static org.elasticsearch.xpack.sql.proto.Protocol.CATALOG_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CLIENT_ID_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CURSOR_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.FETCH_SIZE_NAME; @@ -62,6 +63,7 @@ public abstract class AbstractSqlQueryRequest extends AbstractSqlRequest impleme private String query = ""; private ZoneId zoneId = Protocol.TIME_ZONE; + private String catalog = null; private int fetchSize = Protocol.FETCH_SIZE; private TimeValue requestTimeout = Protocol.REQUEST_TIMEOUT; private TimeValue pageTimeout = Protocol.PAGE_TIMEOUT; @@ -74,6 +76,7 @@ public abstract class AbstractSqlQueryRequest extends AbstractSqlRequest impleme static final ParseField CURSOR = new ParseField(CURSOR_NAME); static final ParseField PARAMS = new ParseField(PARAMS_NAME); static final ParseField TIME_ZONE = new ParseField(TIME_ZONE_NAME); + static final ParseField CATALOG = new ParseField(CATALOG_NAME); static final ParseField FETCH_SIZE = new ParseField(FETCH_SIZE_NAME); static final ParseField REQUEST_TIMEOUT = new ParseField(REQUEST_TIMEOUT_NAME); static final ParseField PAGE_TIMEOUT = new ParseField(PAGE_TIMEOUT_NAME); @@ -87,11 +90,12 @@ public AbstractSqlQueryRequest() { } public AbstractSqlQueryRequest(String query, List params, QueryBuilder filter, Map runtimeMappings, - ZoneId zoneId, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo) { + ZoneId zoneId, String catalog, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo) { super(requestInfo); this.query = query; this.params = params; this.zoneId = zoneId; + this.catalog = catalog; this.fetchSize = fetchSize; this.requestTimeout = requestTimeout; this.pageTimeout = pageTimeout; @@ -109,6 +113,7 @@ protected static ObjectParser objec parser.declareString(AbstractSqlRequest::version, VERSION); parser.declareField(AbstractSqlQueryRequest::params, AbstractSqlQueryRequest::parseParams, PARAMS, ValueType.VALUE_ARRAY); parser.declareString((request, zoneId) -> request.zoneId(ZoneId.of(zoneId)), TIME_ZONE); + parser.declareString(AbstractSqlQueryRequest::catalog, CATALOG); parser.declareInt(AbstractSqlQueryRequest::fetchSize, FETCH_SIZE); parser.declareString((request, timeout) -> request.requestTimeout(TimeValue.parseTimeValue(timeout, Protocol.REQUEST_TIMEOUT, REQUEST_TIMEOUT_NAME)), REQUEST_TIMEOUT); @@ -289,6 +294,15 @@ public AbstractSqlQueryRequest zoneId(ZoneId zoneId) { return this; } + public String catalog() { + return catalog; + } + + public AbstractSqlQueryRequest catalog(String catalog) { + this.catalog = catalog; + return this; + } + /** * Hint about how many results to fetch at once. */ @@ -363,6 +377,9 @@ public AbstractSqlQueryRequest(StreamInput in) throws IOException { query = in.readString(); params = in.readList(AbstractSqlQueryRequest::readSqlTypedParamValue); zoneId = in.readZoneId(); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { // TODO: V_7_16_0 + catalog = in.readOptionalString(); + } fetchSize = in.readVInt(); requestTimeout = in.readTimeValue(); pageTimeout = in.readTimeValue(); @@ -391,6 +408,9 @@ public void writeTo(StreamOutput out) throws IOException { writeSqlTypedParamValue(out, param); } out.writeZoneId(zoneId); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { // TODO: V_7_16_0 + out.writeOptionalString(catalog); + } out.writeVInt(fetchSize); out.writeTimeValue(requestTimeout); out.writeTimeValue(pageTimeout); @@ -416,6 +436,7 @@ public boolean equals(Object o) { Objects.equals(query, that.query) && Objects.equals(params, that.params) && Objects.equals(zoneId, that.zoneId) && + Objects.equals(catalog, that.catalog) && Objects.equals(requestTimeout, that.requestTimeout) && Objects.equals(pageTimeout, that.pageTimeout) && Objects.equals(filter, that.filter) && @@ -424,6 +445,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(super.hashCode(), query, params, zoneId, fetchSize, requestTimeout, pageTimeout, filter, runtimeMappings); + return Objects.hash(super.hashCode(), query, params, zoneId, catalog, fetchSize, requestTimeout, pageTimeout, filter, + runtimeMappings); } } diff --git a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequest.java b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequest.java index 4527a25620534..988864c2f6f65 100644 --- a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequest.java +++ b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequest.java @@ -91,10 +91,10 @@ public SqlQueryRequest() { } public SqlQueryRequest(String query, List params, QueryBuilder filter, Map runtimeMappings, - ZoneId zoneId, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar, + ZoneId zoneId, String catalog, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, Boolean columnar, String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen, TimeValue waitForCompletionTimeout, boolean keepOnCompletion, TimeValue keepAlive) { - super(query, params, filter, runtimeMappings, zoneId, fetchSize, requestTimeout, pageTimeout, requestInfo); + super(query, params, filter, runtimeMappings, zoneId, catalog, fetchSize, requestTimeout, pageTimeout, requestInfo); this.cursor = cursor; this.columnar = columnar; this.fieldMultiValueLeniency = fieldMultiValueLeniency; @@ -266,7 +266,7 @@ public String getDescription() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { // This is needed just to test round-trip compatibility with proto.SqlQueryRequest - return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(query(), params(), zoneId(), fetchSize(), requestTimeout(), + return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(query(), params(), zoneId(), catalog(), fetchSize(), requestTimeout(), pageTimeout(), filter(), columnar(), cursor(), requestInfo(), fieldMultiValueLeniency(), indexIncludeFrozen(), binaryCommunication(), runtimeMappings(), waitForCompletionTimeout(), keepOnCompletion(), keepAlive()) .toXContent(builder, params); diff --git a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestBuilder.java b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestBuilder.java index a1a0f296d3b9f..7f87b3ed6c551 100644 --- a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestBuilder.java +++ b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestBuilder.java @@ -28,19 +28,19 @@ public class SqlQueryRequestBuilder extends ActionRequestBuilder { public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action) { - this(client, action, "", emptyList(), null, emptyMap(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, + this(client, action, "", emptyList(), null, emptyMap(), Protocol.TIME_ZONE, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, false, "", new RequestInfo(Mode.PLAIN), Protocol.FIELD_MULTI_VALUE_LENIENCY, Protocol.INDEX_INCLUDE_FROZEN, Protocol.DEFAULT_WAIT_FOR_COMPLETION_TIMEOUT, Protocol.DEFAULT_KEEP_ON_COMPLETION, Protocol.DEFAULT_KEEP_ALIVE); } public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action, String query, List params, - QueryBuilder filter, Map runtimeMappings, ZoneId zoneId, int fetchSize, TimeValue requestTimeout, - TimeValue pageTimeout, boolean columnar, String nextPageInfo, RequestInfo requestInfo, + QueryBuilder filter, Map runtimeMappings, ZoneId zoneId, String catalog, int fetchSize, + TimeValue requestTimeout, TimeValue pageTimeout, boolean columnar, String nextPageInfo, RequestInfo requestInfo, boolean multiValueFieldLeniency, boolean indexIncludeFrozen, TimeValue waitForCompletionTimeout, boolean keepOnCompletion, TimeValue keepAlive) { - super(client, action, new SqlQueryRequest(query, params, filter, runtimeMappings, zoneId, fetchSize, requestTimeout, pageTimeout, - columnar, nextPageInfo, requestInfo, multiValueFieldLeniency, indexIncludeFrozen, waitForCompletionTimeout, + super(client, action, new SqlQueryRequest(query, params, filter, runtimeMappings, zoneId, catalog, fetchSize, requestTimeout, + pageTimeout, columnar, nextPageInfo, requestInfo, multiValueFieldLeniency, indexIncludeFrozen, waitForCompletionTimeout, keepOnCompletion, keepAlive)); } @@ -84,6 +84,11 @@ public SqlQueryRequestBuilder zoneId(ZoneId zoneId) { return this; } + public SqlQueryRequestBuilder catalog(String catalog) { + request.catalog(catalog); + return this; + } + public SqlQueryRequestBuilder requestTimeout(TimeValue timeout) { request.requestTimeout(timeout); return this; diff --git a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequest.java b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequest.java index 0d775e5888e46..f9b7dd1dc19cc 100644 --- a/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequest.java +++ b/x-pack/plugin/sql/sql-action/src/main/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequest.java @@ -37,7 +37,7 @@ public SqlTranslateRequest() { public SqlTranslateRequest(String query, List params, QueryBuilder filter, Map runtimeMappings, ZoneId zoneId, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo) { - super(query, params, filter, runtimeMappings, zoneId, fetchSize, requestTimeout, pageTimeout, requestInfo); + super(query, params, filter, runtimeMappings, zoneId, null, fetchSize, requestTimeout, pageTimeout, requestInfo); } public SqlTranslateRequest(StreamInput in) throws IOException { @@ -67,7 +67,7 @@ public static SqlTranslateRequest fromXContent(XContentParser parser) { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { // This is needed just to test parsing of SqlTranslateRequest, so we can reuse SqlQuerySerialization - return new SqlQueryRequest(query(), params(), zoneId(), fetchSize(), requestTimeout(), pageTimeout(), + return new SqlQueryRequest(query(), params(), zoneId(), null, fetchSize(), requestTimeout(), pageTimeout(), filter(), null, null, diff --git a/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestTests.java b/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestTests.java index 85b075ba7db07..4aba8c1dffef2 100644 --- a/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestTests.java +++ b/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlQueryRequestTests.java @@ -36,6 +36,7 @@ import static org.elasticsearch.xpack.sql.action.SqlTestUtils.randomFilter; import static org.elasticsearch.xpack.sql.action.SqlTestUtils.randomFilterOrNull; import static org.elasticsearch.xpack.sql.proto.Protocol.BINARY_FORMAT_NAME; +import static org.elasticsearch.xpack.sql.proto.Protocol.CATALOG_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CLIENT_ID_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.COLUMNAR_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CURSOR_NAME; @@ -84,7 +85,7 @@ protected NamedXContentRegistry xContentRegistry() { @Override protected SqlQueryRequest createTestInstance() { return new SqlQueryRequest(randomAlphaOfLength(10), randomParameters(), SqlTestUtils.randomFilterOrNull(random()), - randomRuntimeMappings(), randomZone(), between(1, Integer.MAX_VALUE), randomTV(), + randomRuntimeMappings(), randomZone(), randomAlphaOfLength(10), between(1, Integer.MAX_VALUE), randomTV(), randomTV(), randomBoolean(), randomAlphaOfLength(10), requestInfo, randomBoolean(), randomBoolean(), randomTV(), randomBoolean(), randomTVGreaterThan(MIN_KEEP_ALIVE) ); @@ -103,6 +104,7 @@ protected SqlQueryRequest mutateInstance(SqlQueryRequest instance) { request -> request.query(randomValueOtherThan(request.query(), () -> randomAlphaOfLength(5))), request -> request.params(randomValueOtherThan(request.params(), this::randomParameters)), request -> request.zoneId(randomValueOtherThan(request.zoneId(), ESTestCase::randomZone)), + request -> request.catalog(randomValueOtherThan(request.catalog(), () -> randomAlphaOfLength(10))), request -> request.fetchSize(randomValueOtherThan(request.fetchSize(), () -> between(1, Integer.MAX_VALUE))), request -> request.requestTimeout(randomValueOtherThan(request.requestTimeout(), this::randomTV)), request -> request.filter(randomValueOtherThan(request.filter(), @@ -114,9 +116,9 @@ protected SqlQueryRequest mutateInstance(SqlQueryRequest instance) { request -> request.keepAlive(randomValueOtherThan(request.keepAlive(), () -> randomTVGreaterThan(MIN_KEEP_ALIVE))) ); SqlQueryRequest newRequest = new SqlQueryRequest(instance.query(), instance.params(), instance.filter(), instance.runtimeMappings(), - instance.zoneId(), instance.fetchSize(), instance.requestTimeout(), instance.pageTimeout(), instance.columnar(), - instance.cursor(), instance.requestInfo(), instance.fieldMultiValueLeniency(), instance.indexIncludeFrozen(), - instance.waitForCompletionTimeout(), instance.keepOnCompletion(), instance.keepAlive()); + instance.zoneId(), instance.catalog(), instance.fetchSize(), instance.requestTimeout(), instance.pageTimeout(), + instance.columnar(), instance.cursor(), instance.requestInfo(), instance.fieldMultiValueLeniency(), + instance.indexIncludeFrozen(), instance.waitForCompletionTimeout(), instance.keepOnCompletion(), instance.keepAlive()); mutator.accept(newRequest); return newRequest; } @@ -232,6 +234,9 @@ private static void toXContent(SqlQueryRequest request, XContentBuilder builder) if (request.zoneId() != null) { builder.field(TIME_ZONE_NAME, request.zoneId().getId()); } + if (request.catalog() != null) { + builder.field(CATALOG_NAME, request.catalog()); + } if (request.fetchSize() != Protocol.FETCH_SIZE) { builder.field(FETCH_SIZE_NAME, request.fetchSize()); } diff --git a/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequestTests.java b/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequestTests.java index 4cf8f96735cfa..f6a58203cbad8 100644 --- a/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequestTests.java +++ b/x-pack/plugin/sql/sql-action/src/test/java/org/elasticsearch/xpack/sql/action/SqlTranslateRequestTests.java @@ -74,6 +74,7 @@ protected SqlTranslateRequest mutateInstance(SqlTranslateRequest instance) throw Consumer mutator = randomFrom( request -> request.query(randomValueOtherThan(request.query(), () -> randomAlphaOfLength(5))), request -> request.zoneId(randomValueOtherThan(request.zoneId(), ESTestCase::randomZone)), + request -> request.catalog(randomValueOtherThan(request.catalog(), () -> randomAlphaOfLength(10))), request -> request.fetchSize(randomValueOtherThan(request.fetchSize(), () -> between(1, Integer.MAX_VALUE))), request -> request.requestTimeout(randomValueOtherThan(request.requestTimeout(), this::randomTV)), request -> request.filter(randomValueOtherThan(request.filter(), diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java index 04fc5a1fae7d7..85aa003ed24f1 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java @@ -65,9 +65,13 @@ public class ConnectionConfiguration { // NB: this is password instead of pass since that's what JDBC DriverManager/tools use public static final String AUTH_PASS = "password"; + // Default catalog + + public static final String CATALOG = "catalog"; + protected static final Set OPTION_NAMES = new LinkedHashSet<>( Arrays.asList(PROPERTIES_VALIDATION, BINARY_COMMUNICATION, CONNECT_TIMEOUT, NETWORK_TIMEOUT, QUERY_TIMEOUT, PAGE_TIMEOUT, - PAGE_SIZE, AUTH_USER, AUTH_PASS)); + PAGE_SIZE, AUTH_USER, AUTH_PASS, CATALOG)); static { OPTION_NAMES.addAll(SslConfig.OPTION_NAMES); diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java index 3d0975db216d3..942f6e0606c78 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java @@ -66,7 +66,7 @@ public MainResponse serverInfo() throws SQLException { public SqlQueryResponse basicQuery(String query, int fetchSize) throws SQLException { // TODO allow customizing the time zone - this is what session set/reset/get should be about // method called only from CLI - SqlQueryRequest sqlRequest = new SqlQueryRequest(query, emptyList(), Protocol.TIME_ZONE, + SqlQueryRequest sqlRequest = new SqlQueryRequest(query, emptyList(), Protocol.TIME_ZONE, null, fetchSize, TimeValue.timeValueMillis(cfg.queryTimeout()), TimeValue.timeValueMillis(cfg.pageTimeout()), diff --git a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java index ab96ea46db09d..17dc468150dec 100644 --- a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java +++ b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java @@ -163,6 +163,7 @@ private void assertBinaryRequestForDrivers(boolean isBinary, XContentType xConte SqlQueryRequest request = new SqlQueryRequest(query, null, ZoneId.of("Z"), + randomAlphaOfLength(10), randomIntBetween(1, 100), TimeValue.timeValueMillis(randomNonNegativeLong()), TimeValue.timeValueMillis(randomNonNegativeLong()), diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java index b6ae31a9e5b2a..682bf343a621b 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java @@ -22,6 +22,7 @@ public final class Protocol { public static final String QUERY_NAME = "query"; public static final String CURSOR_NAME = "cursor"; /* request/reply */ public static final String TIME_ZONE_NAME = "time_zone"; + public static final String CATALOG_NAME = "catalog"; public static final String FETCH_SIZE_NAME = "fetch_size"; public static final String REQUEST_TIMEOUT_NAME = "request_timeout"; public static final String PAGE_TIMEOUT_NAME = "page_timeout"; diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java index 694bd93e26059..be79da8891764 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java @@ -21,6 +21,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static org.elasticsearch.xpack.sql.proto.Protocol.BINARY_FORMAT_NAME; +import static org.elasticsearch.xpack.sql.proto.Protocol.CATALOG_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CLIENT_ID_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.COLUMNAR_NAME; import static org.elasticsearch.xpack.sql.proto.Protocol.CURSOR_NAME; @@ -48,6 +49,7 @@ public class SqlQueryRequest extends AbstractSqlRequest { private final String cursor; private final String query; private final ZoneId zoneId; + private final String catalog; private final int fetchSize; private final TimeValue requestTimeout; private final TimeValue pageTimeout; @@ -65,7 +67,7 @@ public class SqlQueryRequest extends AbstractSqlRequest { private final boolean keepOnCompletion; private final TimeValue keepAlive; - public SqlQueryRequest(String query, List params, ZoneId zoneId, int fetchSize, + public SqlQueryRequest(String query, List params, ZoneId zoneId, String catalog, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, ToXContent filter, Boolean columnar, String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen, Boolean binaryCommunication, Map runtimeMappings, TimeValue waitForCompletionTimeout, @@ -74,6 +76,7 @@ public SqlQueryRequest(String query, List params, ZoneId zon this.query = query; this.params = params; this.zoneId = zoneId; + this.catalog = catalog; this.fetchSize = fetchSize; this.requestTimeout = requestTimeout; this.pageTimeout = pageTimeout; @@ -89,17 +92,17 @@ public SqlQueryRequest(String query, List params, ZoneId zon this.keepAlive = keepAlive; } - public SqlQueryRequest(String query, List params, ZoneId zoneId, int fetchSize, + public SqlQueryRequest(String query, List params, ZoneId zoneId, String catalog, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, ToXContent filter, Boolean columnar, String cursor, RequestInfo requestInfo, boolean fieldMultiValueLeniency, boolean indexIncludeFrozen, Boolean binaryCommunication, Map runtimeMappings) { - this(query, params, zoneId, fetchSize, requestTimeout, pageTimeout, filter, columnar, cursor, requestInfo, fieldMultiValueLeniency, - indexIncludeFrozen, binaryCommunication, runtimeMappings, Protocol.DEFAULT_WAIT_FOR_COMPLETION_TIMEOUT, - Protocol.DEFAULT_KEEP_ON_COMPLETION, Protocol.DEFAULT_KEEP_ALIVE); + this(query, params, zoneId, catalog, fetchSize, requestTimeout, pageTimeout, filter, columnar, cursor, requestInfo, + fieldMultiValueLeniency, indexIncludeFrozen, binaryCommunication, runtimeMappings, + Protocol.DEFAULT_WAIT_FOR_COMPLETION_TIMEOUT, Protocol.DEFAULT_KEEP_ON_COMPLETION, Protocol.DEFAULT_KEEP_ALIVE); } public SqlQueryRequest(String cursor, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo, boolean binaryCommunication) { - this("", emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, null, false, + this("", emptyList(), Protocol.TIME_ZONE, null, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, null, false, cursor, requestInfo, Protocol.FIELD_MULTI_VALUE_LENIENCY, Protocol.INDEX_INCLUDE_FROZEN, binaryCommunication, emptyMap()); } @@ -132,6 +135,10 @@ public ZoneId zoneId() { return zoneId; } + public String catalog() { + return catalog; + } + /** * Hint about how many results to fetch at once. @@ -213,6 +220,7 @@ public boolean equals(Object o) { && Objects.equals(query, that.query) && Objects.equals(params, that.params) && Objects.equals(zoneId, that.zoneId) + && Objects.equals(catalog, that.catalog) && Objects.equals(requestTimeout, that.requestTimeout) && Objects.equals(pageTimeout, that.pageTimeout) && Objects.equals(filter, that.filter) @@ -229,7 +237,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(super.hashCode(), query, zoneId, fetchSize, requestTimeout, pageTimeout, + return Objects.hash(super.hashCode(), query, zoneId, catalog, fetchSize, requestTimeout, pageTimeout, filter, columnar, cursor, fieldMultiValueLeniency, indexIncludeFrozen, binaryCommunication, runtimeMappings, waitForCompletionTimeout, keepOnCompletion, keepAlive); } @@ -256,6 +264,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (zoneId != null) { builder.field(TIME_ZONE_NAME, zoneId.getId()); } + if (catalog != null) { + builder.field(CATALOG_NAME, catalog); + } if (fetchSize != Protocol.FETCH_SIZE) { builder.field(FETCH_SIZE_NAME, fetchSize); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java index 2d3fe5c35110c..f183b42fc65d7 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java @@ -312,7 +312,7 @@ protected LogicalPlan rule(UnresolvedRelation plan) { "invalid [" + table + "] resolution to [" + indexResolution + "]"); } LogicalPlan logicalPlan = new EsRelation(plan.source(), indexResolution.get(), plan.frozen()); - SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, table.toString()); + SubQueryAlias sa = new SubQueryAlias(plan.source(), logicalPlan, indexResolution.get().toString()); if (plan.alias() != null) { sa = new SubQueryAlias(plan.source(), sa, plan.alias()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java index 60ab395ad3edf..62ae88480c109 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.sql.plan.logical.command; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.ql.expression.Attribute; import org.elasticsearch.xpack.ql.expression.FieldAttribute; import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern; @@ -29,6 +28,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; +import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class ShowColumns extends Command { @@ -71,8 +71,9 @@ public List output() { @Override public void execute(SqlSession session, ActionListener listener) { String cluster = session.indexResolver().clusterName(); + String cat = hasText(catalog) ? catalog : session.configuration().catalog(); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); - idx = Strings.hasText(catalog) && catalog.equals(cluster) == false ? buildRemoteIndexName(catalog, idx) : idx; + idx = hasText(cat) && cat.equals(cluster) == false ? buildRemoteIndexName(cat, idx) : idx; boolean withFrozen = includeFrozen || session.configuration().includeFrozen(); session.indexResolver().resolveAsMergedMapping(idx, withFrozen, emptyMap(), ActionListener.wrap( diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java index cca8341485d8c..ad3193f98b02b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java @@ -21,6 +21,7 @@ import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import static org.elasticsearch.common.Strings.hasText; public class ShowTables extends Command { @@ -61,6 +62,7 @@ public List output() { @Override public final void execute(SqlSession session, ActionListener listener) { String cat = catalogPattern != null ? catalogPattern.asIndexNameWildcard() : catalog; + cat = hasText(cat) ? cat : session.configuration().catalog(); String idx = index != null ? index : (pattern != null ? pattern.asIndexNameWildcard() : "*"); String regex = pattern != null ? pattern.asJavaRegex() : null; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlClearCursorAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlClearCursorAction.java index 10ab94c0ec9bb..194704e6c2bf4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlClearCursorAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlClearCursorAction.java @@ -47,7 +47,7 @@ public static void operation(PlanExecutor planExecutor, SqlClearCursorRequest re ActionListener listener) { Cursor cursor = Cursors.decodeFromStringWithZone(request.getCursor()).v1(); planExecutor.cleanCursor( - new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, + new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, emptyMap(), request.mode(), StringUtils.EMPTY, request.version(), StringUtils.EMPTY, StringUtils.EMPTY, Protocol.FIELD_MULTI_VALUE_LENIENCY, Protocol.INDEX_INCLUDE_FROZEN), cursor, ActionListener.wrap( diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java index 19c3f0faf2760..4a0ee5a14457f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java @@ -109,9 +109,9 @@ public static void operation(PlanExecutor planExecutor, SqlQueryTask task, SqlQu ClusterService clusterService) { // The configuration is always created however when dealing with the next page, only the timeouts are relevant // the rest having default values (since the query is already created) - SqlConfiguration cfg = new SqlConfiguration(request.zoneId(), request.fetchSize(), request.requestTimeout(), request.pageTimeout(), - request.filter(), request.runtimeMappings(), request.mode(), request.clientId(), request.version(), username, - clusterName(clusterService), request.fieldMultiValueLeniency(), request.indexIncludeFrozen(), + SqlConfiguration cfg = new SqlConfiguration(request.zoneId(), request.catalog(), request.fetchSize(), request.requestTimeout(), + request.pageTimeout(), request.filter(), request.runtimeMappings(), request.mode(), request.clientId(), request.version(), + username, clusterName(clusterService), request.fieldMultiValueLeniency(), request.indexIncludeFrozen(), new TaskId(clusterService.localNode().getId(), task.getId()), task, request.waitForCompletionTimeout(), request.keepOnCompletion(), request.keepAlive()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlTranslateAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlTranslateAction.java index 9b15c1b562aec..1de8222ca0070 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlTranslateAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlTranslateAction.java @@ -53,7 +53,7 @@ public TransportSqlTranslateAction(Settings settings, ClusterService clusterServ protected void doExecute(Task task, SqlTranslateRequest request, ActionListener listener) { sqlLicenseChecker.checkIfSqlAllowed(request.mode()); - SqlConfiguration cfg = new SqlConfiguration(request.zoneId(), request.fetchSize(), + SqlConfiguration cfg = new SqlConfiguration(request.zoneId(), request.catalog(), request.fetchSize(), request.requestTimeout(), request.pageTimeout(), request.filter(), request.runtimeMappings(), request.mode(), request.clientId(), request.version(), username(securityContext), clusterName(clusterService), Protocol.FIELD_MULTI_VALUE_LENIENCY, diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlConfiguration.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlConfiguration.java index f9a8a17ba5f6a..ed3e658c9a03b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlConfiguration.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlConfiguration.java @@ -23,6 +23,8 @@ // Typed object holding properties for a given query public class SqlConfiguration extends org.elasticsearch.xpack.ql.session.Configuration { + @Nullable + private final String catalog; private final int pageSize; private final TimeValue requestTimeout; private final TimeValue pageTimeout; @@ -46,7 +48,8 @@ public class SqlConfiguration extends org.elasticsearch.xpack.ql.session.Configu @Nullable private Map runtimeMappings; - public SqlConfiguration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, QueryBuilder filter, + public SqlConfiguration(ZoneId zi, @Nullable String catalog, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, + QueryBuilder filter, Map runtimeMappings, Mode mode, String clientId, SqlVersion version, String username, String clusterName, @@ -58,6 +61,7 @@ public SqlConfiguration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeV super(zi, username, clusterName, x -> Collections.emptySet()); + this.catalog = catalog; this.pageSize = pageSize; this.requestTimeout = requestTimeout; this.pageTimeout = pageTimeout; @@ -75,17 +79,22 @@ public SqlConfiguration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeV this.keepAlive = keepAlive; } - public SqlConfiguration(ZoneId zi, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, QueryBuilder filter, + public SqlConfiguration(ZoneId zi, @Nullable String catalog, int pageSize, TimeValue requestTimeout, TimeValue pageTimeout, + QueryBuilder filter, Map runtimeMappings, Mode mode, String clientId, SqlVersion version, String username, String clusterName, boolean multiValueFieldLeniency, boolean includeFrozen) { - this(zi, pageSize, requestTimeout, pageTimeout, filter, runtimeMappings, mode, clientId, version, username, clusterName, + this(zi, catalog, pageSize, requestTimeout, pageTimeout, filter, runtimeMappings, mode, clientId, version, username, clusterName, multiValueFieldLeniency, includeFrozen, null, null, Protocol.DEFAULT_WAIT_FOR_COMPLETION_TIMEOUT, Protocol.DEFAULT_KEEP_ON_COMPLETION, Protocol.DEFAULT_KEEP_ALIVE); } + public String catalog() { + return catalog; + } + public int pageSize() { return pageSize; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java index 2637c9b4ce2c2..bac11119b83dc 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java @@ -9,7 +9,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.Client; import org.elasticsearch.client.ParentTaskAssigningClient; -import org.elasticsearch.common.Strings; import org.elasticsearch.tasks.TaskCancelledException; import org.elasticsearch.xpack.ql.expression.function.FunctionRegistry; import org.elasticsearch.xpack.ql.index.IndexResolution; @@ -35,6 +34,7 @@ import java.util.function.Function; import static org.elasticsearch.action.ActionListener.wrap; +import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class SqlSession implements Session { @@ -143,8 +143,9 @@ private void preAnalyze(LogicalPlan parsed, Function act TableIdentifier table = tableInfo.id(); String cluster = table.cluster(); + cluster = hasText(cluster) ? cluster : configuration.catalog(); - String indexPattern = Strings.hasText(cluster) && cluster.equals(configuration.clusterName()) == false ? + String indexPattern = hasText(cluster) && cluster.equals(configuration.clusterName()) == false ? buildRemoteIndexName(cluster, table.index()) : table.index(); boolean includeFrozen = configuration.includeFrozen() || tableInfo.isFrozen(); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java index 5b4f0266e6994..68936e4405426 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java @@ -43,7 +43,7 @@ public final class SqlTestUtils { private SqlTestUtils() {} - public static final SqlConfiguration TEST_CFG = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, + public static final SqlConfiguration TEST_CFG = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, Mode.PLAIN, null, null, null, null, false, false); @@ -51,6 +51,7 @@ public static SqlConfiguration randomConfiguration(ZoneId providedZoneId, SqlVer Mode mode = randomFrom(Mode.values()); long taskId = randomNonNegativeLong(); return new SqlConfiguration(providedZoneId != null ? providedZoneId : randomZone(), + null, randomIntBetween(0, 1000), new TimeValue(randomNonNegativeLong()), new TimeValue(randomNonNegativeLong()), diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java index fb15cf81ebc8c..3fa44179b46b5 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java @@ -30,7 +30,7 @@ public void testDatabaseFunctionOutput() { String clusterName = randomAlphaOfLengthBetween(1, 15); SqlParser parser = new SqlParser(); EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-basic.json", true)); - SqlConfiguration sqlConfig = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, + SqlConfiguration sqlConfig = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, randomFrom(Mode.values()), randomAlphaOfLength(10), null, null, clusterName, randomBoolean(), randomBoolean()); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java index adddfeb7d2b6f..51f3a0f7225f5 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java @@ -29,7 +29,7 @@ public class UserFunctionTests extends ESTestCase { public void testNoUsernameFunctionOutput() { SqlParser parser = new SqlParser(); EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-basic.json", true)); - SqlConfiguration sqlConfig = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, + SqlConfiguration sqlConfig = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, randomFrom(Mode.values()), randomAlphaOfLength(10), null, null, randomAlphaOfLengthBetween(1, 15), diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java index 86d75b7691aa9..eaa2c6facb950 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java @@ -231,7 +231,7 @@ public void testSysColumnsPaginationInOdbcMode() { } private int executeCommandInOdbcModeAndCountRows(String sql) { - final SqlConfiguration config = new SqlConfiguration(DateUtils.UTC, randomIntBetween(1, 15), Protocol.REQUEST_TIMEOUT, + final SqlConfiguration config = new SqlConfiguration(DateUtils.UTC, null, randomIntBetween(1, 15), Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, Mode.ODBC, null, SqlVersion.fromId(Version.CURRENT.id), null, null, false, false); Tuple tuple = sql(sql, emptyList(), config, MAPPING1); @@ -256,7 +256,7 @@ public void onFailure(Exception e) { private void executeCommand(String sql, List params, Mode mode, Consumer consumer, Map mapping) { - final SqlConfiguration config = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, + final SqlConfiguration config = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, mode, null, SqlVersion.fromId(Version.CURRENT.id), null, null, false, false); Tuple tuple = sql(sql, params, config, mapping); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java index 21bb856367694..8ba9d104dbb05 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java @@ -59,7 +59,7 @@ public class SysTablesTests extends ESTestCase { private final IndexInfo alias = new IndexInfo(CLUSTER_NAME, "alias", IndexType.ALIAS); private final IndexInfo frozen = new IndexInfo(CLUSTER_NAME, "frozen", IndexType.FROZEN_INDEX); - private final SqlConfiguration FROZEN_CFG = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, + private final SqlConfiguration FROZEN_CFG = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, Mode.PLAIN, null, null, null, null, false, true); // diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java index 0509a97d1513f..9fe20c99f79d2 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java @@ -39,7 +39,7 @@ public class SysTypesTests extends ESTestCase { private final SqlParser parser = new SqlParser(); private Tuple sql(String sql, Mode mode, SqlVersion version) { - SqlConfiguration configuration = new SqlConfiguration(DateUtils.UTC, Protocol.FETCH_SIZE, + SqlConfiguration configuration = new SqlConfiguration(DateUtils.UTC, null, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, null, mode, null, version, null, null, false, false); EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json", true)); Analyzer analyzer = new Analyzer(configuration, new FunctionRegistry(), IndexResolution.valid(test), null); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlMediaTypeParserTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlMediaTypeParserTests.java index 35aec123f0412..16fc47b37e830 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlMediaTypeParserTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlMediaTypeParserTests.java @@ -95,7 +95,7 @@ private static RestRequest reqWithAccept(String acceptHeader) { protected SqlQueryRequest createTestInstance(boolean binaryCommunication, Mode mode, boolean columnar) { return new SqlQueryRequest(randomAlphaOfLength(10), Collections.emptyList(), null, null, - randomZone(), between(1, Integer.MAX_VALUE), TimeValue.parseTimeValue(randomTimeValue(), null, "test"), + randomZone(), randomAlphaOfLength(9), between(1, Integer.MAX_VALUE), TimeValue.parseTimeValue(randomTimeValue(), null, "test"), TimeValue.parseTimeValue(randomTimeValue(), null, "test"), columnar, randomAlphaOfLength(10), new RequestInfo(mode, randomFrom(randomFrom(CLIENT_IDS), randomAlphaOfLengthBetween(10, 20))), randomBoolean(), randomBoolean(), TimeValue.parseTimeValue(randomTimeValue(), null, "test"), From 32e5746f2ed5624b51edf24dc5dfe11e4183bb81 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Thu, 14 Oct 2021 12:21:32 +0200 Subject: [PATCH 06/12] Apply spotless on previously accepted code Spotless reformat a file. --- .../JdbcCsvSpecIT.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java index 869bf66e5cc1f..d0eb5f93690b6 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCsvSpecIT.java @@ -49,8 +49,10 @@ private static CsvTestCase qualifyFromClause(CsvTestCase testCase) { for (int i = 0; i < query.length();) { int j = query.substring(i).toUpperCase(Locale.ROOT).indexOf(EXTRACT_FN_NAME); j = j >= 0 ? i + j : query.length(); - sb.append(query.substring(i, j).replaceAll("(?i)(FROM)(\\s+)(\\w+|\"[^\"]+\")", - "$1$2" + buildRemoteIndexName(REMOTE_CLUSTER_NAME, "$3"))); + sb.append( + query.substring(i, j) + .replaceAll("(?i)(FROM)(\\s+)(\\w+|\"[^\"]+\")", "$1$2" + buildRemoteIndexName(REMOTE_CLUSTER_NAME, "$3")) + ); boolean inString = false, escaping = false; char stringDelim = 0, crrChar; for (int k = query.indexOf('(', j + EXTRACT_FN_NAME.length()); k >= 0 && k < query.length(); k++) { @@ -91,21 +93,20 @@ private static CsvTestCase qualifyFromClause(CsvTestCase testCase) { @Override public Connection esJdbc() throws SQLException { - Connection connection = esJdbc(connectionProperties()); - if (FROM_QUALIFIED.matcher(csvTestCase().query).matches() == false) { - connection.setCatalog(REMOTE_CLUSTER_NAME); - } - return connection; + Connection connection = esJdbc(connectionProperties()); + if (FROM_QUALIFIED.matcher(csvTestCase().query).matches() == false) { + connection.setCatalog(REMOTE_CLUSTER_NAME); + } + return connection; } - @Override + @Override public boolean isEnabled() { return super.isEnabled() && - // skip single-cluster tests that'd need a CLUSTER clause to work in multi-cluster mode. + // skip single-cluster tests that'd need a CLUSTER clause to work in multi-cluster mode. (DESCRIBE_OR_SHOW.matcher(csvTestCase().query).matches() == false || fileName.startsWith("multi-cluster")); } - @Override protected int fetchSize() { // using a smaller fetchSize for nested documents' tests to uncover bugs From 7a80682971fb9b7ad097c52be07910365e502c73 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Thu, 14 Oct 2021 22:15:42 +0200 Subject: [PATCH 07/12] Address review comments Change member access level, spacing. --- .../elasticsearch/xpack/sql/client/ConnectionConfiguration.java | 2 +- .../org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java index 85aa003ed24f1..7842a3ba68b17 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/ConnectionConfiguration.java @@ -67,7 +67,7 @@ public class ConnectionConfiguration { // Default catalog - public static final String CATALOG = "catalog"; + private static final String CATALOG = "catalog"; protected static final Set OPTION_NAMES = new LinkedHashSet<>( Arrays.asList(PROPERTIES_VALIDATION, BINARY_COMMUNICATION, CONNECT_TIMEOUT, NETWORK_TIMEOUT, QUERY_TIMEOUT, PAGE_TIMEOUT, diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index ce7706116c2bd..3b52989a786c2 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -179,7 +179,7 @@ private static FieldAttribute getFieldAttribute(String name) { } public void testPruneSubQueryAliases() { - ShowTables s = new ShowTables(EMPTY, null, null, null,null, false); + ShowTables s = new ShowTables(EMPTY, null, null, null, null, false); SubQueryAlias plan = new SubQueryAlias(EMPTY, s, "show"); LogicalPlan result = new PruneSubQueryAliases().apply(plan); assertEquals(result, s); From 09bbf4aa6092dadbe5476768167a95aab3d17f92 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Thu, 14 Oct 2021 23:00:42 +0200 Subject: [PATCH 08/12] Address review comments Revert to splitting index string higher up in the execution. --- .../xpack/ql/index/IndexResolver.java | 25 ++++++++++--------- .../xpack/ql/util/RemoteClusterUtils.java | 10 +++----- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java index 1f132b3954e86..17ab016d40d25 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java @@ -73,7 +73,7 @@ import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; -import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.qualifyIndices; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.qualifyAndJoinIndices; import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; public class IndexResolver { @@ -205,11 +205,12 @@ public void resolveNames(String clusterWildcard, String indexWildcard, String ja boolean retrieveIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.STANDARD_INDEX); boolean retrieveFrozenIndices = CollectionUtils.isEmpty(types) || types.contains(IndexType.FROZEN_INDEX); + String[] indexWildcards = Strings.commaDelimitedListToStringArray(indexWildcard); Set indexInfos = new HashSet<>(); if (retrieveAliases) { GetAliasesRequest aliasRequest = new GetAliasesRequest() .local(true) - .aliases(Strings.commaDelimitedListToStringArray(indexWildcard)) + .aliases(indexWildcards) .indicesOptions(IndicesOptions.lenientExpandOpen()); client.admin().indices().getAliases(aliasRequest, wrap(aliases -> { @@ -223,7 +224,7 @@ public void resolveNames(String clusterWildcard, String indexWildcard, String ja } } } - resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, + resolveIndices(clusterWildcard, indexWildcards, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, listener); }, ex -> { @@ -233,7 +234,7 @@ public void resolveNames(String clusterWildcard, String indexWildcard, String ja // in both cases, that is allowed and we continue with the indices request if (ex instanceof IndexNotFoundException || ex instanceof ElasticsearchSecurityException) { - resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, + resolveIndices(clusterWildcard, indexWildcards, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, listener); } else { listener.onFailure(ex); @@ -241,17 +242,17 @@ public void resolveNames(String clusterWildcard, String indexWildcard, String ja }) ); } else { - resolveIndices(clusterWildcard, indexWildcard, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, listener); + resolveIndices(clusterWildcard, indexWildcards, javaRegex, retrieveIndices, retrieveFrozenIndices, indexInfos, listener); } } - private void resolveIndices(String clusterWildcard, String indexWildcard, String javaRegex, boolean retrieveIndices, + private void resolveIndices(String clusterWildcard, String[] indexWildcards, String javaRegex, boolean retrieveIndices, boolean retrieveFrozenIndices, Set indexInfos, ActionListener> listener) { if (retrieveIndices || retrieveFrozenIndices) { if (clusterWildcard == null || simpleMatch(clusterWildcard, clusterName)) { // resolve local indices GetIndexRequest indexRequest = new GetIndexRequest() .local(true) - .indices(Strings.commaDelimitedListToStringArray(indexWildcard)) + .indices(indexWildcards) .features(Feature.SETTINGS) .includeDefaults(false) .indicesOptions(INDICES_ONLY_OPTIONS); @@ -270,24 +271,24 @@ private void resolveIndices(String clusterWildcard, String indexWildcard, String isFrozen ? IndexType.FROZEN_INDEX : IndexType.STANDARD_INDEX)); } } - resolveRemoteIndices(clusterWildcard, indexWildcard, javaRegex, retrieveFrozenIndices, indexInfos, listener); + resolveRemoteIndices(clusterWildcard, indexWildcards, javaRegex, retrieveFrozenIndices, indexInfos, listener); }, listener::onFailure) ); } else { - resolveRemoteIndices(clusterWildcard, indexWildcard, javaRegex, retrieveFrozenIndices, indexInfos, listener); + resolveRemoteIndices(clusterWildcard, indexWildcards, javaRegex, retrieveFrozenIndices, indexInfos, listener); } } else { filterResults(javaRegex, indexInfos, listener); } } - private void resolveRemoteIndices(String clusterWildcard, String indexWildcard, String javaRegex, boolean retrieveFrozenIndices, + private void resolveRemoteIndices(String clusterWildcard, String[] indexWildcards, String javaRegex, boolean retrieveFrozenIndices, Set indexInfos, ActionListener> listener) { if (hasText(clusterWildcard)) { IndicesOptions indicesOptions = retrieveFrozenIndices ? FIELD_CAPS_FROZEN_INDICES_OPTIONS : FIELD_CAPS_INDICES_OPTIONS; - FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(qualifyIndices(clusterWildcard, indexWildcard), indicesOptions, - emptyMap()); + FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(qualifyAndJoinIndices(clusterWildcard, indexWildcards), + indicesOptions, emptyMap()); client.fieldCaps(fieldRequest, wrap(response -> { String[] indices = response.getIndices(); if (indices != null) { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java index be11964094d48..e49dfdd99207c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.ql.util; -import org.elasticsearch.common.Strings; import org.elasticsearch.core.Tuple; import java.util.StringJoiner; @@ -23,13 +22,10 @@ public static Tuple splitQualifiedIndex(String indexName) { Tuple.tuple(null, indexName); } - public static String qualifyIndices(String cluster, String indices) { - if (cluster == null) { - return indices; - } + public static String qualifyAndJoinIndices(String cluster, String[] indices) { StringJoiner sj = new StringJoiner(","); - for (String index : Strings.commaDelimitedListToStringArray(indices)) { - sj.add(buildRemoteIndexName(cluster,index)); + for (String index : indices) { + sj.add(cluster != null ? buildRemoteIndexName(cluster,index) : index); } return sj.toString(); } From 6e337a3adb5cfd71f74eb6802520a5f65cfdcfd9 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Mon, 18 Oct 2021 20:32:14 +0200 Subject: [PATCH 09/12] Address review comments Address review comments --- .../ql/util/RemoteClusterUtilsTests.java | 33 +++++++++++++++++++ .../multi-cluster-with-security/build.gradle | 2 +- .../JdbcCatalogIT.java | 3 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java new file mode 100644 index 0000000000000..6f8bf720536ae --- /dev/null +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java @@ -0,0 +1,33 @@ +/* + * 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.ql.util; + +import org.elasticsearch.core.Tuple; +import org.elasticsearch.test.ESTestCase; + +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.isQualified; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.qualifyAndJoinIndices; +import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; + +public class RemoteClusterUtilsTests extends ESTestCase { + public void testSplitQualifiedIndex() { + String cluster = randomAlphaOfLength(20); + String index = randomAlphaOfLength(30); + assertEquals(Tuple.tuple(cluster, index), splitQualifiedIndex(cluster + ":" + index)); + } + + public void testQualifyAndJoinIndices() { + String[] indices = {"foo", "bar", "bar*", "*foo"}; + assertEquals("cluster:foo,cluster:bar,cluster:bar*,cluster*foo", qualifyAndJoinIndices("cluster", indices)); + } + + public void testIsQualified() { + assertTrue(isQualified("foo:bar")); + assertFalse(isQualified("foobar")); + } +} diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle index c79ef7fbde906..02bc398e3719d 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'elasticsearch.standalone-rest-test' apply plugin: 'elasticsearch.rest-test' dependencies { - testImplementation project(path: xpackModule('eql:qa:common')) + testImplementation project(path: xpackModule('ql:test-fixtures')) } def remoteClusterReg = testClusters.register('remote-cluster') { diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java index 6302da15e6d69..32997e47c3b32 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java @@ -55,7 +55,8 @@ public void testJdbcSetCatalog() throws Exception { assertFalse(rs.next()); es.setCatalog(LOCAL_CLUSTER_NAME); - expectThrows(SQLException.class, ps::executeQuery); + ex = expectThrows(SQLException.class, ps::executeQuery); + assertTrue(ex.getMessage().contains("Unknown index [" + INDEX_NAME + "]")); } } From 20f87b2425dbbd615eeb36793e8f585cedd9d869 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Mon, 18 Oct 2021 21:06:12 +0200 Subject: [PATCH 10/12] Enable test cluster security Enable test cluster security --- .../ql/util/RemoteClusterUtilsTests.java | 2 +- .../multi-cluster-with-security/build.gradle | 4 ++-- .../JdbcCatalogIT.java | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java index 6f8bf720536ae..a6fda9490a438 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtilsTests.java @@ -23,7 +23,7 @@ public void testSplitQualifiedIndex() { public void testQualifyAndJoinIndices() { String[] indices = {"foo", "bar", "bar*", "*foo"}; - assertEquals("cluster:foo,cluster:bar,cluster:bar*,cluster*foo", qualifyAndJoinIndices("cluster", indices)); + assertEquals("cluster:foo,cluster:bar,cluster:bar*,cluster:*foo", qualifyAndJoinIndices("cluster", indices)); } public void testIsQualified() { diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle index 02bc398e3719d..2b0eba1365157 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle @@ -13,7 +13,7 @@ def remoteClusterReg = testClusters.register('remote-cluster') { setting 'node.roles', '[data,ingest,master]' setting 'xpack.ml.enabled', 'false' setting 'xpack.watcher.enabled', 'false' - setting 'xpack.security.enabled', 'false' + setting 'xpack.security.enabled', 'true' setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.security.autoconfiguration.enabled', 'false' @@ -28,7 +28,7 @@ def integTestClusterReg = testClusters.register('integTest') { remoteClusterReg.get().getAllTransportPortURI().collect { "\"$it\"" }.toString() } setting 'cluster.remote.connections_per_cluster', "1" - setting 'xpack.security.enabled', 'false' + setting 'xpack.security.enabled', 'true' setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.security.autoconfiguration.enabled', 'false' diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java index 32997e47c3b32..6b5c47cd19b8b 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java @@ -18,7 +18,9 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; +import java.util.Properties; +import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class JdbcCatalogIT extends JdbcIntegrationTestCase { @@ -84,4 +86,22 @@ public void testCatalogDependentCommands() throws Exception { } } } + + @Override + protected Properties connectionProperties() { + Properties connectionProperties = new Properties(); + connectionProperties.put("timezone", randomZone().getId()); + // in the tests, don't be lenient towards multi values + connectionProperties.put("field.multi.value.leniency", "false"); + // gradle defines + String user = System.getProperty("tests.rest.cluster.remote.user"); + String pass = System.getProperty("tests.rest.cluster.remote.password"); + if (hasText(user)) { + connectionProperties.put("user", user); + } + if (hasText(pass)) { + connectionProperties.put("password", pass); + } + return connectionProperties; + } } From 44e2fe4ab0a63f1eff981aa50c895e337675327b Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Tue, 19 Oct 2021 09:14:14 +0200 Subject: [PATCH 11/12] Fix multi-cluster test authentication Propagate credentials to JdbcIntegrationTestCase hierarchy. --- .../multi-cluster-with-security/build.gradle | 5 +++-- .../JdbcCatalogIT.java | 18 ------------------ .../sql/qa/jdbc/JdbcIntegrationTestCase.java | 5 +++++ .../qa/jdbc/SpecBaseIntegrationTestCase.java | 2 +- .../RemoteClusterAwareSqlRestTestCase.java | 11 ++++++----- 5 files changed, 15 insertions(+), 26 deletions(-) diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle index 2b0eba1365157..6837b36f427c9 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/build.gradle @@ -47,8 +47,9 @@ tasks.named("integTest").configure { useCluster remoteClusterReg doFirst { nonInputProperties.systemProperty 'tests.rest.cluster.remote.host', remoteClusterReg.map(c->c.getAllHttpSocketURI().get(0)) - nonInputProperties.systemProperty 'tests.rest.cluster.remote.user', "test_user" - nonInputProperties.systemProperty 'tests.rest.cluster.remote.password', "x-pack-test-password" + // credentials for both local and remote clusters + nonInputProperties.systemProperty 'tests.rest.cluster.multi.user', "test_user" + nonInputProperties.systemProperty 'tests.rest.cluster.multi.password', "x-pack-test-password" } } tasks.named("check").configure {dependsOn("integTest") } // run these tests as part of the "check" task diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java index 6b5c47cd19b8b..84003547b80c1 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java @@ -86,22 +86,4 @@ public void testCatalogDependentCommands() throws Exception { } } } - - @Override - protected Properties connectionProperties() { - Properties connectionProperties = new Properties(); - connectionProperties.put("timezone", randomZone().getId()); - // in the tests, don't be lenient towards multi values - connectionProperties.put("field.multi.value.leniency", "false"); - // gradle defines - String user = System.getProperty("tests.rest.cluster.remote.user"); - String pass = System.getProperty("tests.rest.cluster.remote.password"); - if (hasText(user)) { - connectionProperties.put("user", user); - } - if (hasText(pass)) { - connectionProperties.put("password", pass); - } - return connectionProperties; - } } diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java index bb5bc725d3919..900e257e9d56f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/JdbcIntegrationTestCase.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.Properties; +import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.xpack.ql.TestUtils.assertNoSearchContexts; import static org.elasticsearch.xpack.sql.qa.jdbc.JdbcTestUtils.JDBC_TIMEZONE; @@ -108,6 +109,10 @@ protected Properties connectionProperties() { connectionProperties.put(JDBC_TIMEZONE, randomZone().getId()); // in the tests, don't be lenient towards multi values connectionProperties.put("field.multi.value.leniency", "false"); + if (hasText(AUTH_USER) && hasText(AUTH_PASS)) { + connectionProperties.put("user", AUTH_USER); + connectionProperties.put("password", AUTH_PASS); + } return connectionProperties; } diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java index a4082eb162cf9..9bb9449f0dd0f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java @@ -121,7 +121,7 @@ protected int fetchSize() { // TODO: use UTC for now until deciding on a strategy for handling date extraction @Override protected Properties connectionProperties() { - Properties connectionProperties = new Properties(); + Properties connectionProperties = super.connectionProperties(); // sets up the credentials (if any) // H2 runs with test JVM's set (randomized) timezone, while the ES node with local test machine's. H2 will not take into account // TZ offsets for some time functions (YEAR/MONTH/HOUR) with timestamps, while ES will normalize the value to the given timezone. // So ES will need to be given the corresponding timezone (i.e. same as with H2's), in order to produce the same results. diff --git a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java index d6be513dd7666..f8616a8c4c77d 100644 --- a/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java +++ b/x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/rest/RemoteClusterAwareSqlRestTestCase.java @@ -30,6 +30,10 @@ public abstract class RemoteClusterAwareSqlRestTestCase extends ESRestTestCase { // client used for loading data on a remote cluster only. private static RestClient remoteClient; + // gradle defines + public static final String AUTH_USER = System.getProperty("tests.rest.cluster.multi.user"); + public static final String AUTH_PASS = System.getProperty("tests.rest.cluster.multi.password"); + @BeforeClass public static void initRemoteClients() throws IOException { String crossClusterHost = System.getProperty("tests.rest.cluster.remote.host"); // gradle defined @@ -85,11 +89,8 @@ protected Settings restClientSettings() { } protected static Settings secureRemoteClientSettings() { - // gradle defines - String user = System.getProperty("tests.rest.cluster.remote.user"); - String pass = System.getProperty("tests.rest.cluster.remote.password"); - if (hasText(user) && hasText(pass)) { - String token = basicAuthHeaderValue(user, new SecureString(pass.toCharArray())); + if (hasText(AUTH_USER) && hasText(AUTH_PASS)) { + String token = basicAuthHeaderValue(AUTH_USER, new SecureString(AUTH_PASS.toCharArray())); return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); } return Settings.EMPTY; From 62229d5a2bd5f6ba942d99892078302ccdd62443 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Tue, 19 Oct 2021 09:22:26 +0200 Subject: [PATCH 12/12] Style fix Remove no longer used imports. --- .../xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java index 84003547b80c1..32997e47c3b32 100644 --- a/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java +++ b/x-pack/plugin/sql/qa/server/multi-cluster-with-security/src/test/java/org/elasticsearch/xpack/sql/qa/multi_cluster_with_security/JdbcCatalogIT.java @@ -18,9 +18,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; -import java.util.Properties; -import static org.elasticsearch.common.Strings.hasText; import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public class JdbcCatalogIT extends JdbcIntegrationTestCase {