diff --git a/mug-guava/src/main/java/com/google/mu/safesql/SafeQuery.java b/mug-guava/src/main/java/com/google/mu/safesql/SafeQuery.java index 7aad9633cd..e59b67a4d0 100644 --- a/mug-guava/src/main/java/com/google/mu/safesql/SafeQuery.java +++ b/mug-guava/src/main/java/com/google/mu/safesql/SafeQuery.java @@ -341,6 +341,10 @@ private SafeQuery guardDashExpression(Substring.Match placeholder) { return query.startsWith("-") && !placeholder.isImmediatelyBetween("(", ")") ? parenthesized() : this; } + private static Iterable skipEmptySubqueries(Iterable iterable) { + return Iterables.filter(iterable, v -> !(v instanceof SafeQuery && v.toString().isEmpty())); + } + /** * An SPI class for subclasses to provide additional translation from * placeholder values to safe query strings. @@ -411,7 +415,7 @@ protected SafeQuery translateLiteral(Substring.Match placeholder, Object value) private String fillInPlaceholder(Substring.Match placeholder, Object value) { validatePlaceholder(placeholder); if (value instanceof Iterable) { - Iterable iterable = (Iterable) value; + Iterable iterable = skipEmptySubqueries((Iterable) value); if (placeholder.isImmediatelyBetween("`", "`")) { // If backquoted, it's a list of symbols return String.join("`, `", Iterables.transform(iterable, v -> backquoted(placeholder, v))); } diff --git a/mug-guava/src/test/java/com/google/mu/safesql/SafeQueryTest.java b/mug-guava/src/test/java/com/google/mu/safesql/SafeQueryTest.java index 95120cf8fb..1d172c5c23 100644 --- a/mug-guava/src/test/java/com/google/mu/safesql/SafeQueryTest.java +++ b/mug-guava/src/test/java/com/google/mu/safesql/SafeQueryTest.java @@ -246,7 +246,7 @@ public void listOfUnquotedEnumsPlaceholder() { } @Test - public void listOfSafeBigQueriesPlaceholder() { + public void listOfSafeQueriesPlaceholder() { assertThat( template("SELECT foo FROM {tbls}") .with(/* tbls */ asList(SafeQuery.of("a"), SafeQuery.of("b")))) @@ -254,7 +254,25 @@ public void listOfSafeBigQueriesPlaceholder() { } @Test - public void listOfSafeBigQueries_disallowed() { + public void listOfSubqueries() { + assertThat( + SafeQuery.of( + "SELECT {exprs} FROM tbl", /* exprs */ + asList(SafeQuery.of("123"), SafeQuery.of("foo")))) + .isEqualTo(SafeQuery.of("SELECT 123, foo FROM tbl")); + } + + @Test + public void listOfSubqueries_emptySubqueryIgnored() { + assertThat( + SafeQuery.of( + "SELECT {exprs} FROM tbl", /* exprs */ + asList(SafeQuery.of("123"), SafeQuery.EMPTY))) + .isEqualTo(SafeQuery.of("SELECT 123 FROM tbl")); + } + + @Test + public void listOfSafeQueries_disallowed() { IllegalArgumentException thrown = assertThrows( IllegalArgumentException.class,