|
51 | 51 | import org.apache.calcite.rex.RexSubQuery; |
52 | 52 | import org.apache.calcite.rex.RexWindow; |
53 | 53 | import org.apache.calcite.rex.RexWindowBound; |
| 54 | +import org.apache.calcite.rex.RexWindowBounds; |
54 | 55 | import org.apache.calcite.sql.JoinType; |
55 | 56 | import org.apache.calcite.sql.SqlAggFunction; |
56 | 57 | import org.apache.calcite.sql.SqlFunction; |
|
69 | 70 | import java.lang.reflect.InvocationTargetException; |
70 | 71 | import java.math.BigDecimal; |
71 | 72 | import java.util.ArrayList; |
| 73 | +import java.util.Collections; |
72 | 74 | import java.util.HashMap; |
| 75 | +import java.util.HashSet; |
73 | 76 | import java.util.List; |
74 | 77 | import java.util.Map; |
| 78 | +import java.util.Set; |
| 79 | +import java.util.stream.Collectors; |
75 | 80 |
|
76 | 81 | /** |
77 | 82 | * Utilities for converting {@link org.apache.calcite.rel.RelNode} into JSON |
@@ -437,6 +442,51 @@ RexNode toRex(RelInput relInput, Object o) { |
437 | 442 | } else { |
438 | 443 | type = rexBuilder.deriveReturnType(operator, rexOperands); |
439 | 444 | } |
| 445 | + |
| 446 | + List<Map> keys; |
| 447 | + if ((operator instanceof SqlAggFunction) |
| 448 | + && ((keys = (List<Map>) map.getOrDefault("partition_keys", null)) != null)) { |
| 449 | + List<RexNode> partKeys = keys.stream().map(k -> toRex(relInput, k)) |
| 450 | + .collect(Collectors.toList()); |
| 451 | + |
| 452 | + keys = (List<Map>) map.getOrDefault("order_keys", Collections.emptyList()); |
| 453 | + List<RexFieldCollation> orderKeys = new ArrayList<>(keys.size()); |
| 454 | + for (Map ok : keys) { |
| 455 | + RexNode left = toRex(relInput, ok.get("field")); |
| 456 | + Set<SqlKind> right = new HashSet<>(); |
| 457 | + if ("DESCENDING".equals(ok.get("direction"))) right.add(SqlKind.DESCENDING); |
| 458 | + right.add("LAST".equals(ok.get("nulls")) ? SqlKind.NULLS_LAST : SqlKind.NULLS_FIRST); |
| 459 | + orderKeys.add(new RexFieldCollation(left, right)); |
| 460 | + } |
| 461 | + |
| 462 | + Map lower = (Map) map.getOrDefault("lower_bound", Collections.emptyMap()); |
| 463 | + Map upper = (Map) map.getOrDefault("upper_bound", Collections.emptyMap()); |
| 464 | + RexWindowBound lowerBound; |
| 465 | + RexWindowBound upperBound; |
| 466 | + |
| 467 | + if (Boolean.TRUE.equals(lower.getOrDefault("unbounded", true))) { |
| 468 | + if (Boolean.TRUE.equals(lower.getOrDefault("preceding", true))) |
| 469 | + lowerBound = RexWindowBounds.UNBOUNDED_PRECEDING; |
| 470 | + else |
| 471 | + lowerBound = RexWindowBounds.UNBOUNDED_FOLLOWING; |
| 472 | + } else { |
| 473 | + lowerBound = RexWindowBounds.CURRENT_ROW; |
| 474 | + } |
| 475 | + if (Boolean.TRUE.equals(upper.getOrDefault("is_current_row", true))) { |
| 476 | + upperBound = RexWindowBounds.CURRENT_ROW; |
| 477 | + } else { |
| 478 | + if (Boolean.TRUE.equals(upper.getOrDefault("preceding", true))) |
| 479 | + upperBound = RexWindowBounds.UNBOUNDED_PRECEDING; |
| 480 | + else |
| 481 | + upperBound = RexWindowBounds.UNBOUNDED_FOLLOWING; |
| 482 | + } |
| 483 | + |
| 484 | + boolean rows = Boolean.TRUE.equals(map.getOrDefault("is_rows", true)); |
| 485 | + return rexBuilder.makeOver(type, (SqlAggFunction) operator, rexOperands, |
| 486 | + partKeys, ImmutableList.copyOf(orderKeys), lowerBound, upperBound, |
| 487 | + rows, true, false, false, false); |
| 488 | + } |
| 489 | + |
440 | 490 | return rexBuilder.makeCall(type, operator, rexOperands); |
441 | 491 | } |
442 | 492 | final Integer input = (Integer) map.get("input"); |
|
0 commit comments