diff --git a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DataLoader.java b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DataLoader.java index ff50a33a0af..d2dffe21e10 100644 --- a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DataLoader.java +++ b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DataLoader.java @@ -43,6 +43,27 @@ public class DataLoader { loadEmpDatasetIntoEs(client); } + public static void createEmptyIndex(RestClient client, String index) throws Exception { + Request request = new Request("PUT", "/" + index); + XContentBuilder createIndex = JsonXContent.contentBuilder().startObject(); + createIndex.startObject("settings"); + { + createIndex.field("number_of_shards", 1); + createIndex.field("number_of_replicas", 1); + } + createIndex.endObject(); + createIndex.startObject("mappings"); + { + createIndex.startObject("properties"); + { + } + createIndex.endObject(); + } + createIndex.endObject().endObject(); + request.setJsonEntity(Strings.toString(createIndex)); + client.performRequest(request); + } + protected static void loadEmpDatasetIntoEs(RestClient client) throws Exception { loadEmpDatasetIntoEs(client, "test_emp", "employees"); loadEmpDatasetWithExtraIntoEs(client, "test_emp_copy", "employees"); diff --git a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DatabaseMetaDataTestCase.java b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DatabaseMetaDataTestCase.java index 08f56b00582..ddd768a639d 100644 --- a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DatabaseMetaDataTestCase.java +++ b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DatabaseMetaDataTestCase.java @@ -71,6 +71,24 @@ public class DatabaseMetaDataTestCase extends JdbcIntegrationTestCase { } } + public void testGetTablesForEmptyIndices() throws Exception { + DataLoader.createEmptyIndex(client(), "test_empty"); + DataLoader.createEmptyIndex(client(), "test_empty_again"); + + try (Connection h2 = LocalH2.anonymousDb(); Connection es = esJdbc()) { + h2.createStatement().executeUpdate("RUNSCRIPT FROM 'classpath:/setup_mock_metadata_get_tables_empty.sql'"); + + CheckedSupplier all = () -> h2.createStatement() + .executeQuery("SELECT '" + clusterName() + "' AS TABLE_CAT, * FROM mock"); + assertResultSets(all.get(), es.getMetaData().getTables("%", "%", "%", null)); + assertResultSets(all.get(), es.getMetaData().getTables("%", "%", "te%", null)); + assertResultSets( + h2.createStatement() + .executeQuery("SELECT '" + clusterName() + "' AS TABLE_CAT, * FROM mock WHERE TABLE_NAME = 'test_empty'"), + es.getMetaData().getTables("%", "%", "test_empty", null)); + } + } + public void testGetTypeOfTables() throws Exception { index("test1", body -> body.field("name", "bob")); index("test2", body -> body.field("name", "bob")); @@ -121,4 +139,13 @@ public class DatabaseMetaDataTestCase extends JdbcIntegrationTestCase { assertResultSets(expected, es.getMetaData().getColumns(null, "%", "%", null)); } } + + public void testColumnsForEmptyTable() throws Exception { + try (Connection h2 = LocalH2.anonymousDb(); Connection es = esJdbc()) { + h2.createStatement().executeUpdate("RUNSCRIPT FROM 'classpath:/setup_mock_metadata_get_columns_empty.sql'"); + + ResultSet expected = h2.createStatement().executeQuery("SELECT '" + clusterName() + "' AS TABLE_CAT, * FROM mock"); + assertResultSets(expected, es.getMetaData().getColumns(null, "%", "%", null)); + } + } } \ No newline at end of file diff --git a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/ShowTablesTestCase.java b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/ShowTablesTestCase.java index 4a6882685a9..af5446176bf 100644 --- a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/ShowTablesTestCase.java +++ b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/ShowTablesTestCase.java @@ -37,4 +37,18 @@ public class ShowTablesTestCase extends JdbcIntegrationTestCase { assertResultSets(expected, es.createStatement().executeQuery("SHOW TABLES")); } } + + public void testEmptyIndex() throws Exception { + DataLoader.createEmptyIndex(client(), "test_empty"); + DataLoader.createEmptyIndex(client(), "test_empty_again"); + + 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', 'BASE TABLE', 'INDEX');"); + h2.createStatement().executeUpdate("INSERT INTO mock VALUES ('test_empty_again', 'BASE 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/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java index 05ba49bbd0d..dd311b299fc 100644 --- a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java +++ b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/SpecBaseIntegrationTestCase.java @@ -66,7 +66,7 @@ public abstract class SpecBaseIntegrationTestCase extends JdbcIntegrationTestCas } protected void loadDataset(RestClient client) throws Exception { - DataLoader.loadEmpDatasetIntoEs(client); + DataLoader.loadDatasetIntoEs(client); } @Override diff --git a/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_columns_empty.sql b/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_columns_empty.sql new file mode 100644 index 00000000000..d3bedc429e0 --- /dev/null +++ b/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_columns_empty.sql @@ -0,0 +1,25 @@ +CREATE TABLE mock ( + TABLE_SCHEM VARCHAR, + TABLE_NAME VARCHAR, + COLUMN_NAME VARCHAR, + DATA_TYPE INTEGER, + TYPE_NAME VARCHAR, + COLUMN_SIZE INTEGER, + BUFFER_LENGTH INTEGER, + DECIMAL_DIGITS INTEGER, + NUM_PREC_RADIX INTEGER, + NULLABLE INTEGER, + REMARKS VARCHAR, + COLUMN_DEF VARCHAR, + SQL_DATA_TYPE INTEGER, + SQL_DATETIME_SUB INTEGER, + CHAR_OCTET_LENGTH INTEGER, + ORDINAL_POSITION INTEGER, + IS_NULLABLE VARCHAR, + SCOPE_CATALOG VARCHAR, + SCOPE_SCHEMA VARCHAR, + SCOPE_TABLE VARCHAR, + SOURCE_DATA_TYPE SMALLINT, + IS_AUTOINCREMENT VARCHAR, + IS_GENERATEDCOLUMN VARCHAR +); diff --git a/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_tables_empty.sql b/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_tables_empty.sql new file mode 100644 index 00000000000..c602e97c4d7 --- /dev/null +++ b/x-pack/plugin/sql/qa/src/main/resources/setup_mock_metadata_get_tables_empty.sql @@ -0,0 +1,15 @@ +CREATE TABLE mock ( + TABLE_SCHEM VARCHAR, + TABLE_NAME VARCHAR, + TABLE_TYPE VARCHAR, + REMARKS VARCHAR, + TYPE_CAT VARCHAR, + TYPE_SCHEM VARCHAR, + TYPE_NAME VARCHAR, + SELF_REFERENCING_COL_NAME VARCHAR, + REF_GENERATION VARCHAR +) AS +SELECT null, 'test_empty', 'BASE TABLE', '', null, null, null, null, null FROM DUAL +UNION ALL +SELECT null, 'test_empty_again', 'BASE TABLE', '', null, null, null, null, null FROM DUAL +; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java index 0b596a1f894..f4acf809c98 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java @@ -338,12 +338,13 @@ public class IndexResolver { return null; }); - if (indices.size() != 1) { - throw new SqlIllegalArgumentException("Incorrect merging of mappings (likely due to a bug) - expect 1 but found [{}]", + if (indices.size() > 1) { + throw new SqlIllegalArgumentException( + "Incorrect merging of mappings (likely due to a bug) - expect at most one but found [{}]", indices.size()); } - return IndexResolution.valid(indices.get(0)); + return IndexResolution.valid(indices.isEmpty() ? new EsIndex(indexNames[0], emptyMap()) : indices.get(0)); } private static EsField createField(String fieldName, Map> globalCaps, diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java index fbd004a71df..d57c090817d 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.stream.Stream; +import static java.util.Collections.singletonMap; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; public class IndexResolverTests extends ESTestCase { @@ -211,6 +212,12 @@ public class IndexResolverTests extends ESTestCase { } } + public void testIndexWithNoMapping() { + Map> versionFC = singletonMap("_version", + singletonMap("_index", new FieldCapabilities("_version", "_version", false, false))); + assertTrue(IndexResolver.mergedMappings("*", new String[] { "empty" }, versionFC).isValid()); + } + public static IndexResolution merge(EsIndex... indices) { return IndexResolver.mergedMappings("*", Stream.of(indices).map(EsIndex::name).toArray(String[]::new), fromMappings(indices)); }