@Override protected String visitFunctionCall(FunctionCall node, Void context) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments()); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } builder.append(formatQualifiedName(node.getName())) .append('(').append(arguments); if (node.getOrderBy().isPresent()) { builder.append(' ').append(formatOrderBy(node.getOrderBy().get(), parameters)); } builder.append(')'); if (node.getFilter().isPresent()) { builder.append(" FILTER ").append(visitFilter(node.getFilter().get(), context)); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), context)); } return builder.toString(); }
@Override public String visitFrameBound(FrameBound node, Void context) { switch (node.getType()) { case UNBOUNDED_PRECEDING: return "UNBOUNDED PRECEDING"; case PRECEDING: return process(node.getValue().get(), context) + " PRECEDING"; case CURRENT_ROW: return "CURRENT ROW"; case FOLLOWING: return process(node.getValue().get(), context) + " FOLLOWING"; case UNBOUNDED_FOLLOWING: return "UNBOUNDED FOLLOWING"; } throw new IllegalArgumentException("unhandled type: " + node.getType()); }
@Override protected String visitFunctionCall(FunctionCall node, Void context) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments()); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } builder.append(formatQualifiedName(node.getName())) .append('(').append(arguments); if (node.getOrderBy().isPresent()) { builder.append(' ').append(formatOrderBy(node.getOrderBy().get(), parameters)); } builder.append(')'); if (node.getFilter().isPresent()) { builder.append(" FILTER ").append(visitFilter(node.getFilter().get(), context)); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), context)); } return builder.toString(); }
@Override public String visitWindowFrame(WindowFrame node, Void context) { StringBuilder builder = new StringBuilder(); builder.append(node.getType().toString()).append(' '); if (node.getEnd().isPresent()) { builder.append("BETWEEN ") .append(process(node.getStart(), context)) .append(" AND ") .append(process(node.getEnd().get(), context)); } else { builder.append(process(node.getStart(), context)); } return builder.toString(); }
@Override public String visitFrameBound(FrameBound node, Void context) { switch (node.getType()) { case UNBOUNDED_PRECEDING: return "UNBOUNDED PRECEDING"; case PRECEDING: return process(node.getValue().get(), context) + " PRECEDING"; case CURRENT_ROW: return "CURRENT ROW"; case FOLLOWING: return process(node.getValue().get(), context) + " FOLLOWING"; case UNBOUNDED_FOLLOWING: return "UNBOUNDED FOLLOWING"; } throw new IllegalArgumentException("unhandled type: " + node.getType()); }
@Override protected String visitLikePredicate(LikePredicate node, Void context) { StringBuilder builder = new StringBuilder(); builder.append('(') .append(process(node.getValue(), context)) .append(" LIKE ") .append(process(node.getPattern(), context)); node.getEscape().ifPresent(escape -> { builder.append(" ESCAPE ") .append(process(escape, context)); }); builder.append(')'); return builder.toString(); }
@Override protected String visitArithmeticUnary(ArithmeticUnaryExpression node, Void context) { String value = process(node.getValue(), context); switch (node.getSign()) { case MINUS: // this is to avoid turning a sequence of "-" into a comment (i.e., "-- comment") String separator = value.startsWith("-") ? " " : ""; return "-" + separator + value; case PLUS: return "+" + value; default: throw new UnsupportedOperationException("Unsupported sign: " + node.getSign()); } }
@Override protected String visitLikePredicate(LikePredicate node, Void context) { StringBuilder builder = new StringBuilder(); builder.append('(') .append(process(node.getValue(), context)) .append(" LIKE ") .append(process(node.getPattern(), context)); node.getEscape().ifPresent(escape -> { builder.append(" ESCAPE ") .append(process(escape, context)); }); builder.append(')'); return builder.toString(); }
@Override public String visitWindowFrame(WindowFrame node, Void context) { StringBuilder builder = new StringBuilder(); builder.append(node.getType().toString()).append(' '); if (node.getEnd().isPresent()) { builder.append("BETWEEN ") .append(process(node.getStart(), context)) .append(" AND ") .append(process(node.getEnd().get(), context)); } else { builder.append(process(node.getStart(), context)); } return builder.toString(); }
@Override protected String visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, Void context) { return new StringBuilder() .append("(") .append(process(node.getValue(), context)) .append(' ') .append(node.getOperator().getValue()) .append(' ') .append(node.getQuantifier().toString()) .append(' ') .append(process(node.getSubquery(), context)) .append(")") .toString(); }
@Override protected String visitIfExpression(IfExpression node, Void context) { StringBuilder builder = new StringBuilder(); builder.append("IF(") .append(process(node.getCondition(), context)) .append(", ") .append(process(node.getTrueValue(), context)); if (node.getFalseValue().isPresent()) { builder.append(", ") .append(process(node.getFalseValue().get(), context)); } builder.append(")"); return builder.toString(); }
@Override protected String visitIfExpression(IfExpression node, Void context) { StringBuilder builder = new StringBuilder(); builder.append("IF(") .append(process(node.getCondition(), context)) .append(", ") .append(process(node.getTrueValue(), context)); if (node.getFalseValue().isPresent()) { builder.append(", ") .append(process(node.getFalseValue().get(), context)); } builder.append(")"); return builder.toString(); }
@Override protected String visitSimpleCaseExpression(SimpleCaseExpression node, Void context) { ImmutableList.Builder<String> parts = ImmutableList.builder(); parts.add("CASE") .add(process(node.getOperand(), context)); for (WhenClause whenClause : node.getWhenClauses()) { parts.add(process(whenClause, context)); } node.getDefaultValue() .ifPresent((value) -> parts.add("ELSE").add(process(value, context))); parts.add("END"); return "(" + Joiner.on(' ').join(parts.build()) + ")"; }
@Override protected String visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, Void context) { return new StringBuilder() .append("(") .append(process(node.getValue(), context)) .append(' ') .append(node.getOperator().getValue()) .append(' ') .append(node.getQuantifier().toString()) .append(' ') .append(process(node.getSubquery(), context)) .append(")") .toString(); }
@Override public String visitWindow(Window node, Void context) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy())); } if (node.getOrderBy().isPresent()) { parts.add(formatOrderBy(node.getOrderBy().get(), parameters)); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), context)); } return '(' + Joiner.on(' ').join(parts) + ')'; }
@Override protected String visitArithmeticUnary(ArithmeticUnaryExpression node, Void context) { String value = process(node.getValue(), context); switch (node.getSign()) { case MINUS: // this is to avoid turning a sequence of "-" into a comment (i.e., "-- comment") String separator = value.startsWith("-") ? " " : ""; return "-" + separator + value; case PLUS: return "+" + value; default: throw new UnsupportedOperationException("Unsupported sign: " + node.getSign()); } }
@Override public String visitWindow(Window node, Void context) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy())); } if (node.getOrderBy().isPresent()) { parts.add(formatOrderBy(node.getOrderBy().get(), parameters)); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), context)); } return '(' + Joiner.on(' ').join(parts) + ')'; }
private String visitFilter(Expression node, Void context) { return "(WHERE " + process(node, context) + ')'; }
public String visitGroupingOperation(GroupingOperation node, Void context) { return "GROUPING (" + joinExpressions(node.getGroupingColumns()) + ")"; }
@Override protected String visitSimpleCaseExpression(SimpleCaseExpression node, Void context) { ImmutableList.Builder<String> parts = ImmutableList.builder(); parts.add("CASE") .add(process(node.getOperand(), context)); for (WhenClause whenClause : node.getWhenClauses()) { parts.add(process(whenClause, context)); } node.getDefaultValue() .ifPresent((value) -> parts.add("ELSE").add(process(value, context))); parts.add("END"); return "(" + Joiner.on(' ').join(parts.build()) + ")"; }