diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Attribute.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Attribute.java index fe26fe54cb469..b8b8adc65df32 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Attribute.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Attribute.java @@ -6,6 +6,7 @@ */ package org.elasticsearch.xpack.ql.expression; +import org.elasticsearch.core.Tuple; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; @@ -13,6 +14,7 @@ import java.util.Objects; import static java.util.Collections.emptyList; +import static org.elasticsearch.xpack.ql.util.StringUtils.splitQualifiedIndex; /** * {@link Expression}s that can be materialized and describe properties of the derived table. @@ -31,6 +33,8 @@ public abstract class Attribute extends NamedExpression { // empty - such as a top level attribute in SELECT cause // present - table name or a table name alias private final String qualifier; + // cluster name in the qualifier (if any) + private final String cluster; // can the attr be null - typically used in JOINs private final Nullability nullability; @@ -45,7 +49,14 @@ public Attribute(Source source, String name, String qualifier, Nullability nulla public Attribute(Source source, String name, String qualifier, Nullability nullability, NameId id, boolean synthetic) { super(source, name, emptyList(), id, synthetic); - this.qualifier = qualifier; + if (qualifier != null) { + Tuple splitQualifier = splitQualifiedIndex(qualifier); + this.cluster = splitQualifier.v1(); + this.qualifier = splitQualifier.v2(); + } else { + this.cluster = null; + this.qualifier = null; + } this.nullability = nullability; } 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 724d980e4942d..c70ae804435a3 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,8 +73,8 @@ 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.qualifyAndJoinIndices; -import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; +import static org.elasticsearch.xpack.ql.util.StringUtils.qualifyAndJoinIndices; +import static org.elasticsearch.xpack.ql.util.StringUtils.splitQualifiedIndex; public class IndexResolver { 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 deleted file mode 100644 index 825b351f18f19..0000000000000 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/RemoteClusterUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.ql.util; - -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 qualifyAndJoinIndices(String cluster, String[] indices) { - StringJoiner sj = new StringJoiner(","); - for (String index : indices) { - sj.add(cluster != null ? buildRemoteIndexName(cluster, index) : index); - } - return sj.toString(); - } - - public static boolean isQualified(String indexWildcard) { - return indexWildcard.indexOf(REMOTE_CLUSTER_INDEX_SEPARATOR) > 0; - } -} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/StringUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/StringUtils.java index c1c05b2d2ec96..1b021af0f9ec9 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/StringUtils.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/StringUtils.java @@ -21,8 +21,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.StringJoiner; import static java.util.stream.Collectors.toList; +import static org.elasticsearch.transport.RemoteClusterAware.REMOTE_CLUSTER_INDEX_SEPARATOR; +import static org.elasticsearch.transport.RemoteClusterAware.buildRemoteIndexName; public final class StringUtils { @@ -334,4 +337,23 @@ public static String ordinal(int i) { } } + + 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 qualifyAndJoinIndices(String cluster, String[] indices) { + StringJoiner sj = new StringJoiner(","); + for (String index : indices) { + sj.add(cluster != null ? buildRemoteIndexName(cluster, index) : index); + } + return sj.toString(); + } + + public static boolean isQualified(String indexWildcard) { + return indexWildcard.indexOf(REMOTE_CLUSTER_INDEX_SEPARATOR) > 0; + } } 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 fbedc38fc138c..c0bd746048ae5 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 @@ -10,9 +10,9 @@ 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; +import static org.elasticsearch.xpack.ql.util.StringUtils.isQualified; +import static org.elasticsearch.xpack.ql.util.StringUtils.qualifyAndJoinIndices; +import static org.elasticsearch.xpack.ql.util.StringUtils.splitQualifiedIndex; public class RemoteClusterUtilsTests extends ESTestCase { public void testSplitQualifiedIndex() { 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 5c252d1a1aa20..6a1c08413abea 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 @@ -70,6 +70,30 @@ public void testQueryCatalogPrecedence() throws Exception { } } + public void testQueryWithQualifierAndSetCatalog() throws Exception { + try (Connection es = esJdbc()) { + PreparedStatement ps = es.prepareStatement("SELECT " + INDEX_NAME + ".zero FROM " + INDEX_NAME); + es.setCatalog(REMOTE_CLUSTER_NAME); + ResultSet rs = ps.executeQuery(); + assertTrue(rs.next()); + assertEquals(0, rs.getInt(1)); + assertFalse(rs.next()); + } + } + + public void testQueryWithQualifiedFieldAndIndex() throws Exception { + try (Connection es = esJdbc()) { + PreparedStatement ps = es.prepareStatement( + "SELECT " + INDEX_NAME + ".zero FROM " + buildRemoteIndexName(REMOTE_CLUSTER_NAME, INDEX_NAME) + ); + es.setCatalog(LOCAL_CLUSTER_NAME); // set, but should be ignored + ResultSet rs = ps.executeQuery(); + assertTrue(rs.next()); + assertEquals(0, rs.getInt(1)); + assertFalse(rs.next()); + } + } + public void testCatalogDependentCommands() throws Exception { for (String query : List.of( "SHOW TABLES \"" + INDEX_NAME + "\"", 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 80cc9fb86280d..14992e9e8f926 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 @@ -41,8 +41,8 @@ import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; import static org.elasticsearch.xpack.ql.type.DataTypes.isPrimitive; import static org.elasticsearch.xpack.ql.type.DataTypes.isString; -import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.isQualified; -import static org.elasticsearch.xpack.ql.util.RemoteClusterUtils.splitQualifiedIndex; +import static org.elasticsearch.xpack.ql.util.StringUtils.isQualified; +import static org.elasticsearch.xpack.ql.util.StringUtils.splitQualifiedIndex; import static org.elasticsearch.xpack.sql.type.SqlDataTypes.displaySize; import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlDataType; import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlDateTimeSub;