Skip to content

Commit af3b7c5

Browse files
authored
fix(bigquery-jdbc): Add escape character support for pattern matching (#13259)
1 parent b2bc2d4 commit af3b7c5

2 files changed

Lines changed: 38 additions & 26 deletions

File tree

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaData.java

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5080,40 +5080,35 @@ Pattern compileSqlLikePattern(String sqlLikePattern) {
50805080
}
50815081
StringBuilder regex = new StringBuilder(sqlLikePattern.length() * 2);
50825082
regex.append('^');
5083+
boolean escaped = false;
50835084
for (int i = 0; i < sqlLikePattern.length(); i++) {
50845085
char c = sqlLikePattern.charAt(i);
5085-
switch (c) {
5086-
case '%':
5087-
regex.append(".*");
5088-
break;
5089-
case '_':
5090-
regex.append('.');
5091-
break;
5092-
case '\\':
5093-
case '.':
5094-
case '[':
5095-
case ']':
5096-
case '(':
5097-
case ')':
5098-
case '{':
5099-
case '}':
5100-
case '*':
5101-
case '+':
5102-
case '?':
5103-
case '^':
5104-
case '$':
5105-
case '|':
5106-
regex.append('\\').append(c);
5107-
break;
5108-
default:
5109-
regex.append(c);
5110-
break;
5086+
if (!escaped && c == '\\') {
5087+
escaped = true;
5088+
continue;
5089+
} else if (!escaped && c == '%') {
5090+
regex.append(".*");
5091+
} else if (!escaped && c == '_') {
5092+
regex.append('.');
5093+
} else {
5094+
if (isRegexMetacharacter(c)) {
5095+
regex.append('\\');
5096+
}
5097+
regex.append(c);
5098+
escaped = false;
51115099
}
51125100
}
5101+
if (escaped) {
5102+
regex.append('\\').append('\\');
5103+
}
51135104
regex.append('$');
51145105
return Pattern.compile(regex.toString(), Pattern.CASE_INSENSITIVE);
51155106
}
51165107

5108+
private static boolean isRegexMetacharacter(char c) {
5109+
return "\\.[]{}()*+?^$|".indexOf(c) != -1;
5110+
}
5111+
51175112
boolean needsListing(String pattern) {
51185113
return pattern == null || pattern.contains("%") || pattern.contains("_");
51195114
}

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryDatabaseMetaDataTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,23 @@ public void testCompileSqlLikePattern() {
243243
assertNotNull(bracketPattern);
244244
assertTrue(bracketPattern.matcher("array[0]").matches());
245245
assertFalse(bracketPattern.matcher("array_0_").matches());
246+
247+
// Escaped wildcards
248+
Pattern escapedUnderscore = dbMetadata.compileSqlLikePattern("test\\_table");
249+
assertNotNull(escapedUnderscore);
250+
assertTrue(escapedUnderscore.matcher("test_table").matches());
251+
assertFalse(escapedUnderscore.matcher("test1table").matches());
252+
253+
Pattern escapedPercent = dbMetadata.compileSqlLikePattern("100\\%discount");
254+
assertNotNull(escapedPercent);
255+
assertTrue(escapedPercent.matcher("100%discount").matches());
256+
assertFalse(escapedPercent.matcher("100PERCENTdiscount").matches());
257+
258+
// Escape character at the end
259+
Pattern escapeLast = dbMetadata.compileSqlLikePattern("test\\");
260+
assertNotNull(escapeLast);
261+
assertTrue(escapeLast.matcher("test\\").matches());
262+
assertFalse(escapeLast.matcher("test").matches());
246263
}
247264

248265
@Test

0 commit comments

Comments
 (0)