use of io.crate.planner.operators.LogicalPlan in project crate by crate.
the class ExplainPlan method executeOrFail.
@Override
public void executeOrFail(DependencyCarrier dependencies, PlannerContext plannerContext, RowConsumer consumer, Row params, SubQueryResults subQueryResults) {
if (context != null) {
assert subPlan instanceof LogicalPlan : "subPlan must be a LogicalPlan";
LogicalPlan plan = (LogicalPlan) subPlan;
/**
* EXPLAIN ANALYZE does not support analyzing {@link io.crate.planner.MultiPhasePlan}s
*/
if (plan.dependencies().isEmpty()) {
UUID jobId = plannerContext.jobId();
BaseResultReceiver resultReceiver = new BaseResultReceiver();
RowConsumer noopRowConsumer = new RowConsumerToResultReceiver(resultReceiver, 0, t -> {
});
Timer timer = context.createTimer(Phase.Execute.name());
timer.start();
NodeOperationTree operationTree = LogicalPlanner.getNodeOperationTree(plan, dependencies, plannerContext, params, subQueryResults);
resultReceiver.completionFuture().whenComplete(createResultConsumer(dependencies, consumer, jobId, timer, operationTree));
LogicalPlanner.executeNodeOpTree(dependencies, plannerContext.transactionContext(), jobId, noopRowConsumer, true, operationTree);
} else {
consumer.accept(null, new UnsupportedOperationException("EXPLAIN ANALYZE does not support profiling multi-phase plans, " + "such as queries with scalar subselects."));
}
} else {
if (subPlan instanceof LogicalPlan) {
PrintContext printContext = new PrintContext();
((LogicalPlan) subPlan).print(printContext);
consumer.accept(InMemoryBatchIterator.of(new Row1(printContext.toString()), SENTINEL), null);
} else if (subPlan instanceof CopyFromPlan) {
ExecutionPlan executionPlan = CopyFromPlan.planCopyFromExecution(((CopyFromPlan) subPlan).copyFrom(), dependencies.clusterService().state().nodes(), plannerContext, params, subQueryResults);
String planAsJson = DataTypes.STRING.implicitCast(PlanPrinter.objectMap(executionPlan));
consumer.accept(InMemoryBatchIterator.of(new Row1(planAsJson), SENTINEL), null);
} else {
consumer.accept(InMemoryBatchIterator.of(new Row1("EXPLAIN not supported for " + subPlan.getClass().getSimpleName()), SENTINEL), null);
}
}
}
use of io.crate.planner.operators.LogicalPlan in project crate by crate.
the class UpdatePlanner method plan.
public static Plan plan(AnalyzedUpdateStatement update, PlannerContext plannerCtx, SubqueryPlanner subqueryPlanner) {
if (update.outputs() != null && !plannerCtx.clusterState().getNodes().getMinNodeVersion().onOrAfter(Version.V_4_2_0)) {
throw new UnsupportedFeatureException(RETURNING_VERSION_ERROR_MSG);
}
AbstractTableRelation<?> table = update.table();
Plan plan;
if (table instanceof DocTableRelation) {
DocTableRelation docTable = (DocTableRelation) table;
plan = plan(docTable, update.assignmentByTargetCol(), update.query(), plannerCtx, update.outputs());
} else {
plan = new Update((plannerContext, params, subQueryValues) -> sysUpdate(plannerContext, (TableRelation) table, update.assignmentByTargetCol(), update.query(), params, subQueryValues, update.outputs()));
}
Map<LogicalPlan, SelectSymbol> subQueries = subqueryPlanner.planSubQueries(update);
return MultiPhasePlan.createIfNeeded(plan, subQueries);
}
use of io.crate.planner.operators.LogicalPlan in project crate by crate.
the class MoveFilterBeneathGroupBy method apply.
@Override
public LogicalPlan apply(Filter filter, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
// Since something like `SELECT x, sum(y) FROM t GROUP BY x HAVING y > 10` is not valid
// (y would have to be declared as group key) any parts of a HAVING that is not an aggregation can be moved.
Symbol predicate = filter.query();
List<Symbol> parts = AndOperator.split(predicate);
ArrayList<Symbol> withAggregates = new ArrayList<>();
ArrayList<Symbol> withoutAggregates = new ArrayList<>();
for (Symbol part : parts) {
if (SymbolVisitors.any(Symbols::isAggregate, part)) {
withAggregates.add(part);
} else {
withoutAggregates.add(part);
}
}
if (withoutAggregates.isEmpty()) {
return null;
}
GroupHashAggregate groupBy = captures.get(groupByCapture);
if (withoutAggregates.size() == parts.size()) {
return transpose(filter, groupBy);
}
/* HAVING `count(*) > 1 AND x = 10`
* withAggregates: [count(*) > 1]
* withoutAggregates: [x = 10]
*
* Filter
* |
* GroupBy
*
* transforms to
*
* Filter (count(*) > 1)
* |
* GroupBy
* |
* Filter (x = 10)
*/
LogicalPlan newGroupBy = groupBy.replaceSources(List.of(new Filter(groupBy.source(), AndOperator.join(withoutAggregates))));
return new Filter(newGroupBy, AndOperator.join(withAggregates));
}
use of io.crate.planner.operators.LogicalPlan in project crate by crate.
the class MoveFilterBeneathUnion method apply.
@Override
public LogicalPlan apply(Filter filter, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
Union union = captures.get(unionCapture);
LogicalPlan lhs = union.sources().get(0);
LogicalPlan rhs = union.sources().get(1);
return union.replaceSources(List.of(createNewFilter(filter, lhs), createNewFilter(filter, rhs)));
}
use of io.crate.planner.operators.LogicalPlan in project crate by crate.
the class MoveOrderBeneathNestedLoop method apply.
@Override
public LogicalPlan apply(Order order, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
NestedLoopJoin nestedLoop = captures.get(nlCapture);
Set<RelationName> relationsInOrderBy = Collections.newSetFromMap(new IdentityHashMap<>());
Consumer<ScopedSymbol> gatherRelationsFromField = f -> relationsInOrderBy.add(f.relation());
Consumer<Reference> gatherRelationsFromRef = r -> relationsInOrderBy.add(r.ident().tableIdent());
OrderBy orderBy = order.orderBy();
for (Symbol orderExpr : orderBy.orderBySymbols()) {
FieldsVisitor.visitFields(orderExpr, gatherRelationsFromField);
RefVisitor.visitRefs(orderExpr, gatherRelationsFromRef);
}
if (relationsInOrderBy.size() == 1) {
RelationName relationInOrderBy = relationsInOrderBy.iterator().next();
if (relationInOrderBy == nestedLoop.topMostLeftRelation().relationName()) {
LogicalPlan lhs = nestedLoop.sources().get(0);
LogicalPlan newLhs = order.replaceSources(List.of(lhs));
return new NestedLoopJoin(newLhs, nestedLoop.sources().get(1), nestedLoop.joinType(), nestedLoop.joinCondition(), nestedLoop.isFiltered(), nestedLoop.topMostLeftRelation(), true, nestedLoop.isRewriteFilterOnOuterJoinToInnerJoinDone());
}
}
return null;
}
Aggregations