diff --git a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java index be03e25e3c6..9acb8d215c1 100644 --- a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java +++ b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java @@ -113,7 +113,7 @@ public class JdbcAssert { } else if (type == Types.DOUBLE) { - // NOCOMMIT 1d/1f seems like a huge difference. + // the 1d/1f difference is used due to rounding/flooring assertEquals(msg, (double) expectedObject, (double) actualObject, 1d); } else if (type == Types.FLOAT) { assertEquals(msg, (float) expectedObject, (float) actualObject, 1f); diff --git a/sql/jdbc-proto/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/protocol/MetaColumnRequest.java b/sql/jdbc-proto/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/protocol/MetaColumnRequest.java index 3ab6762666b..af17b83b4fa 100644 --- a/sql/jdbc-proto/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/protocol/MetaColumnRequest.java +++ b/sql/jdbc-proto/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/protocol/MetaColumnRequest.java @@ -57,8 +57,8 @@ public class MetaColumnRequest extends Request { return false; } MetaColumnRequest other = (MetaColumnRequest) obj; - return tablePattern.equals(other.tablePattern) - && columnPattern.equals(other.columnPattern); + return Objects.equals(tablePattern, other.tablePattern) + && Objects.equals(columnPattern, other.columnPattern); } @Override diff --git a/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcDatabaseMetaData.java b/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcDatabaseMetaData.java index a4ca72161ab..1cd95372e77 100644 --- a/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcDatabaseMetaData.java +++ b/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcDatabaseMetaData.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.List; import static org.elasticsearch.xpack.sql.net.client.util.StringUtils.EMPTY; -import static org.elasticsearch.xpack.sql.net.client.util.StringUtils.hasText; /** * Implementation of {@link DatabaseMetaData} for Elasticsearch. Draws inspiration @@ -684,26 +683,32 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper { } private boolean isDefaultCatalog(String catalog) throws SQLException { + // null means catalog info is irrelevant + // % means return all catalogs + // "" means return those without a catalog return catalog == null || catalog.equals(EMPTY) || catalog.equals("%") || catalog.equals(defaultCatalog()); } private boolean isDefaultSchema(String schema) { + // null means schema info is irrelevant + // % means return all schemas + // "" means return those without a schema return schema == null || schema.equals(EMPTY) || schema.equals("%"); } @Override public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { List info = columnInfo("TABLES", - "TABLE_CAT", - "TABLE_SCHEM", - "TABLE_NAME", - "TABLE_TYPE", - "REMARKS", - "TYPE_CAT", - "TYPE_SCHEM", - "TYPE_NAME", - "SELF_REFERENCING_COL_NAME", - "REF_GENERATION"); + "TABLE_CAT", //0 + "TABLE_SCHEM", //1 + "TABLE_NAME", //2 + "TABLE_TYPE", //3 + "REMARKS", //4 + "TYPE_CAT", //5 + "TYPE_SCHEM", //6 + "TYPE_NAME", //7 + "SELF_REFERENCING_COL_NAME", //8 + "REF_GENERATION"); //9 // schema and catalogs are not being used, if these are specified return an empty result set if (!isDefaultCatalog(catalog) || !isDefaultSchema(schemaPattern)) { @@ -711,7 +716,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper { } String cat = defaultCatalog(); - List tables = con.client.metaInfoTables(sqlWildcardToSimplePattern(tableNamePattern)); + List tables = con.client.metaInfoTables(tableNamePattern); Object[][] data = new Object[tables.size()][]; for (int i = 0; i < data.length; i++) { data[i] = new Object[10]; @@ -731,23 +736,6 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper { return memorySet(con.cfg, info, data); } - /** - * Convert sql wildcards ({@code %} and @{code _}) into {@code Regex#simpleMatch}-style patterns. - */ - private static String sqlWildcardToSimplePattern(String pattern) { - // NOCOMMIT ? isn't supported by simple pattern - // NOCOMMIT escape *? - return hasText(pattern) ? pattern.replaceAll("%", "*").replace('_', '?') : pattern; - } - - /** - * Convert sql wildcards ({@code %} and @{code _}) into regex style patterns. - */ - private static String sqlWildcardToRegexPattern(String pattern) { - // NOCOMMIT escape regex bits? - return hasText(pattern) ? pattern.replaceAll("%", ".*").replace('_', '.') : pattern; - } - @Override public ResultSet getSchemas() throws SQLException { Object[][] data = { { EMPTY, defaultCatalog() } }; @@ -818,8 +806,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper { } String cat = defaultCatalog(); - List columns = con.client.metaInfoColumns( - sqlWildcardToSimplePattern(tableNamePattern), sqlWildcardToRegexPattern(columnNamePattern)); + // escaping is done on the server + List columns = con.client.metaInfoColumns(tableNamePattern, columnNamePattern); Object[][] data = new Object[columns.size()][]; for (int i = 0; i < data.length; i++) { data[i] = new Object[24]; diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/util/StringUtils.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/util/StringUtils.java index e34b35c687d..4d4a3166579 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/util/StringUtils.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/util/StringUtils.java @@ -115,6 +115,7 @@ public abstract class StringUtils { char curr = sqlPattern.charAt(i); if (shouldEscape && !escaped && (curr == escapeChar)) { escaped = true; + regex.append(curr); } else { switch (curr) { @@ -143,7 +144,9 @@ public abstract class StringUtils { case ']': case '{': case '}': - regex.append('\\'); + if (!escaped) { + regex.append('\\'); + } } regex.append(curr); @@ -166,7 +169,7 @@ public abstract class StringUtils { } public static Pattern likeRegex(String likePattern) { - return Pattern.compile(sqlToJavaPattern(likePattern, '\\', true)); + return Pattern.compile(sqlToJavaPattern(likePattern)); } public static String toString(SearchSourceBuilder source) { diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/util/StringUtilsTest.java b/sql/server/src/test/java/org/elasticsearch/xpack/sql/util/StringUtilsTest.java new file mode 100644 index 00000000000..7a8fb126b31 --- /dev/null +++ b/sql/server/src/test/java/org/elasticsearch/xpack/sql/util/StringUtilsTest.java @@ -0,0 +1,54 @@ +/* + * 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.util; + +import org.junit.Test; + +import static org.elasticsearch.xpack.sql.util.StringUtils.sqlToJavaPattern; +import static org.junit.Assert.assertEquals; + +public class StringUtilsTest { + + @Test + public void testNoRegex() { + assertEquals("^fooBar$", sqlToJavaPattern("fooBar")); + } + + @Test + public void testEscapedJavaRegex() { + assertEquals("^\\.\\d$", sqlToJavaPattern("\\.\\d")); + } + + @Test + public void testSimpleSqlRegex1() { + assertEquals("^foo.bar$", sqlToJavaPattern("foo_bar")); + } + + @Test + public void testSimpleSqlRegex2() { + assertEquals("^foo.*bar$", sqlToJavaPattern("foo%bar")); + } + + @Test + public void testMultipleSqlRegexes() { + assertEquals("^foo.*bar.$", sqlToJavaPattern("foo%bar_")); + } + + @Test + public void testJavaRegexNoSqlRegex() { + assertEquals("^foo\\.\\*bar$", sqlToJavaPattern("foo.*bar")); + } + + @Test + public void testMultipleRegexAndSqlRegex() { + assertEquals("^foo\\.\\*bar\\..*$", sqlToJavaPattern("foo.*bar.%")); + } + + @Test + public void testComplicatedJavaRegex() { + assertEquals("^\\^\\[\\d\\]\\.\\*\\$$", sqlToJavaPattern("^[\\d].*$")); + } +}