|
2 | 2 |
|
3 | 3 | import static java.util.Collections.emptyMap; |
4 | 4 | import static java.util.Objects.requireNonNull; |
| 5 | +import static java.util.stream.Collectors.collectingAndThen; |
| 6 | +import static java.util.stream.Collectors.mapping; |
5 | 7 |
|
6 | 8 | import java.math.BigDecimal; |
7 | 9 | import java.time.Instant; |
|
16 | 18 | import java.util.Map; |
17 | 19 | import java.util.Objects; |
18 | 20 | import java.util.Optional; |
| 21 | +import java.util.function.BiConsumer; |
| 22 | +import java.util.function.Predicate; |
19 | 23 | import java.util.stream.Collector; |
| 24 | +import java.util.stream.Collector.Characteristics; |
20 | 25 | import java.util.stream.Stream; |
21 | 26 |
|
22 | 27 | import com.google.cloud.bigquery.BigQuery.JobOption; |
@@ -117,6 +122,16 @@ private ParameterizedQuery( |
117 | 122 | */ |
118 | 123 | public static ParameterizedQuery EMPTY = of(""); |
119 | 124 |
|
| 125 | + /** |
| 126 | + * Returns a query using a compile-time constant query with no parameters. |
| 127 | + * |
| 128 | + * @since 8.2 |
| 129 | + */ |
| 130 | + @TemplateFormatMethod |
| 131 | + public static ParameterizedQuery of(@CompileTimeConstant @TemplateString String query) { |
| 132 | + return new ParameterizedQuery(query, emptyMap(), emptyMap()); |
| 133 | + } |
| 134 | + |
120 | 135 | /** |
121 | 136 | * Convenience method when you need to create the {@link ParameterizedQuery} inline, with both the |
122 | 137 | * query template and the arguments. |
@@ -225,6 +240,36 @@ public static Stream<ParameterizedQuery> enumConstants(Class<? extends Enum<?>> |
225 | 240 | .map(e -> new ParameterizedQuery(e.name(), emptyMap(), emptyMap())); |
226 | 241 | } |
227 | 242 |
|
| 243 | + /** |
| 244 | + * A collector that joins boolean query snippets using {@code AND} operator. The |
| 245 | + * AND'ed sub-queries will be enclosed in pairs of parenthesis to avoid |
| 246 | + * ambiguity. If the input is empty, the result will be "TRUE". |
| 247 | + * |
| 248 | + * <p>Empty ParameterizedQuery elements are ignored and not joined. |
| 249 | + * |
| 250 | + * @since 8.2 |
| 251 | + */ |
| 252 | + public static Collector<ParameterizedQuery, ?, ParameterizedQuery> and() { |
| 253 | + return collectingAndThen( |
| 254 | + nonEmptyQueries(mapping(ParameterizedQuery::parenthesized, joining(" AND "))), |
| 255 | + query -> query.query.isEmpty() ? of("TRUE") : query); |
| 256 | + } |
| 257 | + |
| 258 | + /** |
| 259 | + * A collector that joins boolean query snippets using {@code OR} operator. The |
| 260 | + * OR'ed sub-queries will be enclosed in pairs of parenthesis to avoid |
| 261 | + * ambiguity. If the input is empty, the result will be "FALSE". |
| 262 | + * |
| 263 | + * <p>Empty ParameterizedQuery elements are ignored and not joined. |
| 264 | + * |
| 265 | + * @since 8.2 |
| 266 | + */ |
| 267 | + public static Collector<ParameterizedQuery, ?, ParameterizedQuery> or() { |
| 268 | + return collectingAndThen( |
| 269 | + nonEmptyQueries(mapping(ParameterizedQuery::parenthesized, joining(" OR "))), |
| 270 | + query -> query.query.isEmpty() ? of("FALSE") : query); |
| 271 | + } |
| 272 | + |
228 | 273 | /** |
229 | 274 | * Returns a collector that joins ParameterizedQuery elements using {@code delimiter}. |
230 | 275 | * |
@@ -391,4 +436,25 @@ public boolean equals(Object obj) { |
391 | 436 | public String toString() { |
392 | 437 | return query; |
393 | 438 | } |
| 439 | + |
| 440 | + private ParameterizedQuery parenthesized() { |
| 441 | + return new ParameterizedQuery("(" + query + ")", emptyMap(), emptyMap()); |
| 442 | + } |
| 443 | + |
| 444 | + private static <R> Collector<ParameterizedQuery, ?, R> nonEmptyQueries( |
| 445 | + Collector<ParameterizedQuery, ?, R> downstream) { |
| 446 | + return filtering(q -> !q.query.isEmpty(), downstream); |
| 447 | + } |
| 448 | + |
| 449 | + // Not in Java 8 |
| 450 | + private static <T, A, R> Collector<T, A, R> filtering( |
| 451 | + Predicate<? super T> filter, Collector<? super T, A, R> collector) { |
| 452 | + BiConsumer<A, ? super T> accumulator = collector.accumulator(); |
| 453 | + return Collector.of( |
| 454 | + collector.supplier(), |
| 455 | + (a, input) -> {if (filter.test(input)) {accumulator.accept(a, input);}}, |
| 456 | + collector.combiner(), |
| 457 | + collector.finisher(), |
| 458 | + collector.characteristics().toArray(new Characteristics[0])); |
| 459 | + } |
394 | 460 | } |
0 commit comments