diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaData.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaData.java index 1c6834feb27d..86fa0d84cec1 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaData.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaData.java @@ -5080,40 +5080,32 @@ Pattern compileSqlLikePattern(String sqlLikePattern) { } StringBuilder regex = new StringBuilder(sqlLikePattern.length() * 2); regex.append('^'); + boolean escaped = false; for (int i = 0; i < sqlLikePattern.length(); i++) { char c = sqlLikePattern.charAt(i); - switch (c) { - case '%': - regex.append(".*"); - break; - case '_': - regex.append('.'); - break; - case '\\': - case '.': - case '[': - case ']': - case '(': - case ')': - case '{': - case '}': - case '*': - case '+': - case '?': - case '^': - case '$': - case '|': - regex.append('\\').append(c); - break; - default: - regex.append(c); - break; + if (!escaped && c == '\\') { + escaped = true; + continue; + } else if (!escaped && c == '%') { + regex.append(".*"); + } else if (!escaped && c == '_') { + regex.append('.'); + } else { + if (isRegexMetacharacter(c)) { + regex.append('\\'); + } + regex.append(c); + escaped = false; } } regex.append('$'); return Pattern.compile(regex.toString(), Pattern.CASE_INSENSITIVE); } + private static boolean isRegexMetacharacter(char c) { + return "\\.[]{}()*+?^$|".indexOf(c) != -1; + } + boolean needsListing(String pattern) { return pattern == null || pattern.contains("%") || pattern.contains("_"); } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaDataTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaDataTest.java index 654cdbe0ff7c..78adda7b2dc6 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaDataTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaDataTest.java @@ -243,6 +243,17 @@ public void testCompileSqlLikePattern() { assertNotNull(bracketPattern); assertTrue(bracketPattern.matcher("array[0]").matches()); assertFalse(bracketPattern.matcher("array_0_").matches()); + + // Escaped wildcards + Pattern escapedUnderscore = dbMetadata.compileSqlLikePattern("test\\_table"); + assertNotNull(escapedUnderscore); + assertTrue(escapedUnderscore.matcher("test_table").matches()); + assertFalse(escapedUnderscore.matcher("test1table").matches()); + + Pattern escapedPercent = dbMetadata.compileSqlLikePattern("100\\%discount"); + assertNotNull(escapedPercent); + assertTrue(escapedPercent.matcher("100%discount").matches()); + assertFalse(escapedPercent.matcher("100PERCENTdiscount").matches()); } @Test