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 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; }
new RakamSqlFormatter.Formatter(builder, name -> queryExecutor.formatTableReference(context.project, name, Optional.empty(), sessionProperties), '"').process(statement, 1);
Query statement = (Query) SqlUtil.parseSql(materializedView.query); new RakamSqlFormatter.Formatter(builder, name -> queryExecutor .formatTableReference(context.project, name, Optional.empty(), new HashMap<String, String>() { @Override }), '"').process(statement, 1);
builder.append("IF NOT EXISTS "); String tableName = formatName(node.getName()); builder.append(tableName).append(" (\n"); String elementIndent = indentString(indent + 1); String columnList = node.getElements().stream() .map(element -> { StringBuilder builder = new StringBuilder(elementIndent); builder.append("LIKE ") .append(formatName(likeClause.getTableName())); if (likeClause.getPropertiesOption().isPresent()) { builder.append(" ") builder.append(formatProperties(node.getProperties()));
new RakamSqlFormatter.Formatter(builder, qualifiedName -> { String prefix = qualifiedName.getPrefix().get().getPrefix().get().toString(); if (!prefix.equals("external")) { }, seperator).process(sqlParser.createStatement(query, new ParsingOptions(ParsingOptions.DecimalLiteralTreatment.AS_DOUBLE)), 1);
.collect(Collectors.toList())); append(indent, "WITH"); if (with.isRecursive()) { builder.append(" RECURSIVE"); while (queries.hasNext()) { WithQuery query = queries.next(); append(indent, formatExpression(query.getName(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)); query.getColumnNames().ifPresent(columnNames -> appendAliasColumns(builder, columnNames)); builder.append(" AS "); process(new TableSubquery(query.getQuery()), indent); builder.append('\n'); if (queries.hasNext()) { processRelation(node.getQueryBody(), indent); process(node.getOrderBy().get(), indent);
} else if ((queryStatement instanceof Call)) { StringBuilder builder = new StringBuilder(); new RakamSqlFormatter.Formatter(builder, tableNameMapper, escapeIdentifier) .process(queryStatement, 1); return builder.toString(); } else { new RakamSqlFormatter.Formatter(builder, tableNameMapper, escapeIdentifier) .process(statement, 1);
@Override protected Void visitQuerySpecification(QuerySpecification node, Integer indent) { process(node.getSelect(), indent); if (node.getFrom().isPresent()) { append(indent, "FROM"); builder.append('\n'); append(indent, " "); process(node.getFrom().get(), indent); } builder.append('\n'); if (node.getWhere().isPresent()) { append(indent, "WHERE " + formatExpression(node.getWhere().get(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)) .append('\n'); } if (node.getGroupBy().isPresent()) { append(indent, "GROUP BY " + (node.getGroupBy().get().isDistinct() ? " DISTINCT " : "") + formatGroupBy(node.getGroupBy().get().getGroupingElements())).append('\n'); } if (node.getHaving().isPresent()) { append(indent, "HAVING " + formatExpression(node.getHaving().get(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)) .append('\n'); } if (node.getOrderBy().isPresent()) { process(node.getOrderBy().get(), indent); } if (node.getLimit().isPresent()) { append(indent, "LIMIT " + node.getLimit().get()) .append('\n'); } return null; }
public CompletableFuture<List<SchemaField>> metadata(RequestContext context, String query) { StringBuilder builder = new StringBuilder(); Query queryStatement; try { queryStatement = (Query) SqlUtil.parseSql(checkNotNull(query, "query is required")); } catch (Exception e) { throw new RakamException("Unable to parse query: " + e.getMessage(), BAD_REQUEST); } Map<String, String> map = new HashMap<>(); new RakamSqlFormatter.Formatter(builder, qualifiedName -> executor.formatTableReference(context.project, qualifiedName, Optional.empty(), map), escapeIdentifier) .process(queryStatement, 1); QueryExecution execution = executor .executeRawQuery(context, builder.toString() + " limit 0", map); CompletableFuture<List<SchemaField>> f = new CompletableFuture<>(); execution.getResult().thenAccept(result -> { if (result.isFailed()) { f.completeExceptionally(new RakamException(result.getError().message, HttpResponseStatus.INTERNAL_SERVER_ERROR)); } else { f.complete(result.getMetadata()); } }); return f; } }
@Override public CompletableFuture<Void> create(RequestContext context, MaterializedView materializedView) { Query statement = (Query) sqlParser.createStatement(materializedView.query, new ParsingOptions()); StringBuilder builder = new StringBuilder(); HashMap<String, String> map = new HashMap<>(); new RakamSqlFormatter.Formatter(builder, qualifiedName -> queryExecutor.formatTableReference(context.project, qualifiedName, Optional.empty(), map), '"') .process(statement, 1); QueryExecution execution = queryExecutor .executeRawStatement(context, format("create table %s as %s limit 0", queryExecutor.formatTableReference(context.project, QualifiedName.of("materialized", materializedView.tableName), Optional.empty(), ImmutableMap.of()), builder.toString(), Optional.empty()), map); return execution.getResult().thenAccept(result -> { try { get(context.project, materializedView.tableName); throw new AlreadyExistsException("Materialized view", BAD_REQUEST); } catch (NotExistsException e) { } if (result.isFailed()) { throw new RakamException(result.getError().message, INTERNAL_SERVER_ERROR); } else { database.createMaterializedView(context.project, materializedView); } }); }
@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 visitShowPartitions(ShowPartitions node, Integer context) { builder.append("SHOW PARTITIONS FROM ") .append(formatName(node.getTable())); if (node.getWhere().isPresent()) { builder.append(" WHERE ") .append(formatExpression(node.getWhere().get(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)); } if (!node.getOrderBy().isEmpty()) { builder.append(" ORDER BY ") .append(formatSortItems(node.getOrderBy(), tableNameMapper, columnNameMapper, queryWithTables, escapeIdentifier)); } if (node.getLimit().isPresent()) { builder.append(" LIMIT ") .append(node.getLimit().get()); } return null; }
@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 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; }
@Test public void testQueryWithCTE() throws Exception { Statement statement = new SqlParser().createStatement("with test as (select * from collection) select * from test"); assertEquals(formatQuery(statement, name -> "dummy", '"').trim(), "WITH\n" + " \"test\" AS (\n" + " SELECT *\n" + " FROM\n" + " dummy\n" + " ) \n" + " SELECT *\n" + " FROM\n" + " test"); }