@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 Node visitExplain(Explain node, Void context) { Statement statement = (Statement) process(node.getStatement(), null); return new Explain( node.getLocation().get(), node.isAnalyze(), node.isVerbose(), statement, node.getOptions()); }
@Override protected R visitExplain(Explain node, C context) { process(node.getStatement(), context); for (ExplainOption option : node.getOptions()) { process(option, context); } return null; }
@Override public Node visitExplain(SqlBaseParser.ExplainContext context) { return new Explain(getLocation(context), context.ANALYZE() != null, context.VERBOSE() != null, (Statement) visit(context.statement()), visit(context.explainOption(), ExplainOption.class)); }
public PreparedQuery prepareQuery(Session session, Statement wrappedStatement) throws ParsingException, PrestoException, SemanticException { Statement statement = unwrapExecuteStatement(wrappedStatement, sqlParser, session); if (statement instanceof Explain && ((Explain) statement).isAnalyze()) { Statement innerStatement = ((Explain) statement).getStatement(); Optional<QueryType> innerQueryType = StatementUtils.getQueryType(innerStatement.getClass()); if (!innerQueryType.isPresent() || innerQueryType.get() == QueryType.DATA_DEFINITION) { throw new PrestoException(NOT_SUPPORTED, "EXPLAIN ANALYZE doesn't support statement type: " + innerStatement.getClass().getSimpleName()); } } List<Expression> parameters = ImmutableList.of(); if (wrappedStatement instanceof Execute) { parameters = ((Execute) wrappedStatement).getParameters(); } validateParameters(statement, parameters); return new PreparedQuery(statement, parameters); }
private Node getQueryPlan(Explain node, ExplainType.Type planType, ExplainFormat.Type planFormat) throws IllegalArgumentException { PreparedQuery preparedQuery = queryPreparer.prepareQuery(session, node.getStatement()); if (planType == VALIDATE) { queryExplainer.get().analyze(session, preparedQuery.getStatement(), preparedQuery.getParameters(), warningCollector); return singleValueQuery("Valid", true); } String plan; switch (planFormat) { case GRAPHVIZ: plan = queryExplainer.get().getGraphvizPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; case JSON: plan = queryExplainer.get().getJsonPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; case TEXT: plan = queryExplainer.get().getPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; default: throw new IllegalArgumentException("Invalid Explain Format: " + planFormat.toString()); } return singleValueQuery("Query Plan", plan); }
private RelationPlan createExplainAnalyzePlan(Analysis analysis, Explain statement) { RelationPlan underlyingPlan = planStatementWithoutOutput(analysis, statement.getStatement()); PlanNode root = underlyingPlan.getRoot(); Scope scope = analysis.getScope(statement); Symbol outputSymbol = symbolAllocator.newSymbol(scope.getRelationType().getFieldByIndex(0)); root = new ExplainAnalyzeNode(idAllocator.getNextId(), root, outputSymbol, statement.isVerbose()); return new RelationPlan(root, scope, ImmutableList.of(outputSymbol)); }
private RelationPlan planStatementWithoutOutput(Analysis analysis, Statement statement) { if (statement instanceof CreateTableAsSelect) { if (analysis.isCreateTableAsSelectNoOp()) { throw new PrestoException(NOT_SUPPORTED, "CREATE TABLE IF NOT EXISTS is not supported in this context " + statement.getClass().getSimpleName()); } return createTableCreationPlan(analysis, ((CreateTableAsSelect) statement).getQuery()); } else if (statement instanceof Insert) { checkState(analysis.getInsert().isPresent(), "Insert handle is missing"); return createInsertPlan(analysis, (Insert) statement); } else if (statement instanceof Delete) { return createDeletePlan(analysis, (Delete) statement); } else if (statement instanceof Query) { return createRelationPlan(analysis, (Query) statement); } else if (statement instanceof Explain && ((Explain) statement).isAnalyze()) { return createExplainAnalyzePlan(analysis, (Explain) statement); } else { throw new PrestoException(NOT_SUPPORTED, "Unsupported statement type " + statement.getClass().getSimpleName()); } }
@Override protected R visitExplain(Explain node, C context) { process(node.getStatement(), context); for (ExplainOption option : node.getOptions()) { process(option, context); } return null; }
@Test public void testExplainAnalyze() { assertStatement("EXPLAIN ANALYZE SELECT * FROM t", new Explain(simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), true, false, ImmutableList.of())); }
if (((Explain) statement).isAnalyze()) { return statementToQueryType(((Explain) statement).getStatement());
private String getQueryPlan(Explain node, ExplainType.Type planType, ExplainFormat.Type planFormat) throws IllegalArgumentException { switch (planFormat) { case GRAPHVIZ: return queryExplainer.get().getGraphvizPlan(session, node.getStatement(), planType); case TEXT: return queryExplainer.get().getPlan(session, node.getStatement(), planType); } throw new IllegalArgumentException("Invalid Explain Format: " + planFormat.toString()); }
private PlanRoot doAnalyzeQuery() { // time analysis phase stateMachine.beginAnalysis(); // plan query PlanNodeIdAllocator idAllocator = new PlanNodeIdAllocator(); LogicalPlanner logicalPlanner = new LogicalPlanner(stateMachine.getSession(), planOptimizers, idAllocator, metadata, sqlParser, statsCalculator, costCalculator, stateMachine.getWarningCollector()); Plan plan = logicalPlanner.plan(analysis); queryPlan.set(plan); // extract inputs List<Input> inputs = new InputExtractor(metadata, stateMachine.getSession()).extractInputs(plan.getRoot()); stateMachine.setInputs(inputs); // extract output Optional<Output> output = new OutputExtractor().extractOutput(plan.getRoot()); stateMachine.setOutput(output); // fragment the plan SubPlan fragmentedPlan = planFragmenter.createSubPlans(stateMachine.getSession(), plan, false); // record analysis time stateMachine.endAnalysis(); boolean explainAnalyze = analysis.getStatement() instanceof Explain && ((Explain) analysis.getStatement()).isAnalyze(); return new PlanRoot(fragmentedPlan, !explainAnalyze, extractConnectors(analysis)); }
@Override protected Scope visitExplain(Explain node, Optional<Scope> scope) throws SemanticException { checkState(node.isAnalyze(), "Non analyze explain should be rewritten to Query"); if (node.getOptions().stream().anyMatch(option -> !option.equals(new ExplainType(DISTRIBUTED)))) { throw new SemanticException(NOT_SUPPORTED, node, "EXPLAIN ANALYZE only supports TYPE DISTRIBUTED option"); } process(node.getStatement(), scope); analysis.setUpdateType(null); return createAndAssignScope(node, scope, Field.newUnqualified("Query Plan", VARCHAR)); }
@Override protected Node visitExplain(Explain node, Void context) throws SemanticException { if (node.isAnalyze()) { Statement statement = (Statement) process(node.getStatement(), context); return new Explain(statement, node.isAnalyze(), node.isVerbose(), node.getOptions()); } ExplainType.Type planType = LOGICAL; ExplainFormat.Type planFormat = TEXT; List<ExplainOption> options = node.getOptions(); for (ExplainOption option : options) { if (option instanceof ExplainType) { planType = ((ExplainType) option).getType(); // Use JSON as the default format for EXPLAIN (TYPE IO). if (planType == IO) { planFormat = JSON; } break; } } for (ExplainOption option : options) { if (option instanceof ExplainFormat) { planFormat = ((ExplainFormat) option).getType(); break; } } return getQueryPlan(node, planType, planFormat); }
@Override protected Void visitExplain(Explain node, Integer indent) { builder.append("EXPLAIN "); 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; }
@Test public void testExplainAnalyzeVerbose() { assertStatement("EXPLAIN ANALYZE VERBOSE SELECT * FROM t", new Explain(simpleQuery(selectList(new AllColumns()), table(QualifiedName.of("t"))), true, true, ImmutableList.of())); }
/** * Builds the request defined within the explain statement and returns its string representation * @param sql * @param explain * @param indexes * @return * @throws SQLException */ public String explain(String sql, Explain explain, String... indexes) throws SQLException { com.facebook.presto.sql.tree.Statement explanSt = explain.getStatement(); if(!(explanSt instanceof Query)) throw new SQLException("Can only EXPLAIN SELECT ... statements"); this.buildRequest(sql, ((Query)explanSt).getQueryBody(), indexes); return this.request.toString(); }
root = createOutputPlan(createRelationPlan(analysis, (Query) statement), analysis); else if (statement instanceof Explain && ((Explain) statement).isAnalyze()) { throw new PrestoException(NOT_SUPPORTED, "EXPLAIN ANALYZE not yet implemented");
@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; }