@Override protected Void visitStartTransaction(StartTransaction node, Integer indent) { builder.append("START TRANSACTION"); Iterator<TransactionMode> iterator = node.getTransactionModes().iterator(); while (iterator.hasNext()) { builder.append(" "); process(iterator.next(), indent); if (iterator.hasNext()) { builder.append(","); } } return null; }
private void processRelation(Relation relation, Integer indent) { // TODO: handle this properly if (relation instanceof Table) { builder.append("TABLE ") .append(tableNameMapper.apply(((Table) relation).getName())) .append('\n'); } else { process(relation, indent); } }
@Override protected Void visitCall(Call node, Integer indent) { builder.append("CALL ") .append(node.getName()) .append("("); Iterator<CallArgument> arguments = node.getArguments().iterator(); while (arguments.hasNext()) { process(arguments.next(), indent); if (arguments.hasNext()) { builder.append(", "); } } builder.append(")"); return null; }
@Override protected Void visitExplain(Explain node, Integer indent) { builder.append("EXPLAIN "); if (node.isAnalyze()) { builder.append("ANALYZE "); } List<String> options = new ArrayList<>(); for (ExplainOption option : node.getOptions()) { if (option instanceof ExplainType) { options.add("TYPE " + ((ExplainType) option).getType()); } else if (option instanceof ExplainFormat) { options.add("FORMAT " + ((ExplainFormat) option).getType()); } else { throw new UnsupportedOperationException("unhandled explain option: " + option); } } if (!options.isEmpty()) { builder.append("("); Joiner.on(", ").appendTo(builder, options); builder.append(")"); } builder.append("\n"); process(node.getStatement(), indent); return null; }
@Override protected Void visitSelect(Select node, Integer indent) { append(indent, "SELECT"); if (node.isDistinct()) { builder.append(" DISTINCT"); } if (node.getSelectItems().size() > 1) { boolean first = true; for (SelectItem item : node.getSelectItems()) { builder.append("\n") .append(indentString(indent)) .append(first ? " " : ", "); process(item, indent); first = false; } } else { builder.append(' '); process(getOnlyElement(node.getSelectItems()), indent); } builder.append('\n'); return null; }
protected CompletableFuture<List<SchemaField>> metadata(RequestContext context, String query) { StringBuilder builder = new StringBuilder(); Query queryStatement = (Query) SqlUtil.parseSql(query); CompletableFuture<List<SchemaField>> f = new CompletableFuture<>(); try { new RakamSqlFormatter.Formatter(builder, qualifiedName -> queryExecutor.formatTableReference(context.project, qualifiedName, Optional.empty(), ImmutableMap.of()), escapeIdentifier) .process(queryStatement, 1); } catch (Exception e) { f.completeExceptionally(e); } QueryExecution execution = queryExecutor.executeRawQuery(context, builder.toString() + " limit 0", ZoneOffset.UTC, ImmutableMap.of()); execution.getResult().thenAccept(result -> { if (result.isFailed()) { f.completeExceptionally(new RakamException(result.getError().message, INTERNAL_SERVER_ERROR)); } else { f.complete(result.getMetadata()); } }); return f; }
@Override protected Void visitCreateTableAsSelect(CreateTableAsSelect node, Integer indent) { builder.append("CREATE TABLE "); if (node.isNotExists()) { builder.append("IF NOT EXISTS "); } builder.append(formatName(node.getName())); if (node.getColumnAliases().isPresent()) { String columnList = node.getColumnAliases().get().stream().map(element -> formatExpression(element, tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)).collect(joining(", ")); builder.append(format("( %s )", columnList)); } if (node.getComment().isPresent()) { builder.append("\nCOMMENT " + formatStringLiteral(node.getComment().get())); } builder.append(formatProperties(node.getProperties())); builder.append(" AS "); process(node.getQuery(), indent); if (!node.isWithData()) { builder.append(" WITH NO DATA"); } return null; }
@Override protected Void visitRow(Row node, Integer indent) { builder.append("ROW("); boolean firstItem = true; for (Expression item : node.getItems()) { if (!firstItem) { builder.append(", "); } process(item, indent); firstItem = false; } builder.append(")"); return null; }
@Override protected Void visitInsert(Insert node, Integer indent) { builder.append("INSERT INTO ") .append(node.getTarget()) .append(" "); if (node.getColumns().isPresent()) { builder.append("(") .append(Joiner.on(", ").join(node.getColumns().get())) .append(") "); } process(node.getQuery(), indent); return null; }
@Override protected Void visitShowStats(ShowStats node, Integer context) { builder.append("SHOW STATS FOR "); process(node.getRelation(), 0); builder.append(""); return null; }
@Override protected Void visitCreateView(CreateView node, Integer indent) { builder.append("CREATE "); if (node.isReplace()) { builder.append("OR REPLACE "); } builder.append("VIEW ") .append(formatName(node.getName())) .append(" AS\n"); process(node.getQuery(), indent); return null; }
@Override protected Void visitAliasedRelation(AliasedRelation node, Integer indent) { process(node.getRelation(), indent); builder.append(' ') .append(formatExpression(node.getAlias(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)); appendAliasColumns(builder, node.getColumnNames()); return null; }
@Override protected Void visitLateral(Lateral node, Integer indent) { append(indent, "LATERAL ("); process(node.getQuery(), indent + 1); append(indent, ")"); return null; }
static String formatSql(Node root, Function<QualifiedName, String> tableNameMapper, Function<String, String> columnNameMapper, List<String> ctes, char escapeIdentifier) { StringBuilder builder = new StringBuilder(); new Formatter(builder, tableNameMapper, columnNameMapper, ctes, escapeIdentifier).process(root, 0); return builder.toString(); }
@Override protected Void visitPrepare(Prepare node, Integer indent) { append(indent, "PREPARE "); builder.append(node.getName()); builder.append(" FROM"); builder.append("\n"); process(node.getStatement(), indent + 1); return null; }
@Override protected Void visitSampledRelation(SampledRelation node, Integer indent) { process(node.getRelation(), indent); builder.append(" TABLESAMPLE ") .append(node.getType()) .append(" (") .append(node.getSamplePercentage()) .append(')'); return null; }
public static String formatSql(Node root, Function<QualifiedName, String> tableNameMapper, Function<String, String> columnNameMapper, char escapeIdentifier) { StringBuilder builder = new StringBuilder(); new Formatter(builder, tableNameMapper, columnNameMapper, escapeIdentifier).process(root, 0); return builder.toString(); }
@Override protected Void visitTableSubquery(TableSubquery node, Integer indent) { builder.append('(') .append('\n'); process(node.getQuery(), indent + 1); append(indent, ") "); return null; }
public static String formatQuery(Statement query, Function<QualifiedName, String> tableNameMapper, char escapeIdentifier) { StringBuilder builder = new StringBuilder(); new RakamSqlFormatter.Formatter(builder, tableNameMapper, escapeIdentifier).process(query, 1); return builder.toString(); }
public static String formatSql(Node root, Function<QualifiedName, String> tableNameMapper, char escapeIdentifier) { StringBuilder builder = new StringBuilder(); new Formatter(builder, tableNameMapper, null, escapeIdentifier).process(root, 0); return builder.toString(); }