use of io.trino.sql.planner.plan.PatternRecognitionNode in project trino by trinodb.
the class PushDownProjectionsFromPatternRecognition method apply.
@Override
public Result apply(PatternRecognitionNode node, Captures captures, Context context) {
Assignments.Builder assignments = Assignments.builder();
Map<IrLabel, ExpressionAndValuePointers> rewrittenVariableDefinitions = rewriteVariableDefinitions(node.getVariableDefinitions(), assignments, context);
Map<Symbol, Measure> rewrittenMeasureDefinitions = rewriteMeasureDefinitions(node.getMeasures(), assignments, context);
if (assignments.build().isEmpty()) {
return Result.empty();
}
assignments.putIdentities(node.getSource().getOutputSymbols());
ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), node.getSource(), assignments.build());
PatternRecognitionNode patternRecognitionNode = new PatternRecognitionNode(node.getId(), projectNode, node.getSpecification(), node.getHashSymbol(), node.getPrePartitionedInputs(), node.getPreSortedOrderPrefix(), node.getWindowFunctions(), rewrittenMeasureDefinitions, node.getCommonBaseFrame(), node.getRowsPerMatch(), node.getSkipToLabel(), node.getSkipToPosition(), node.isInitial(), node.getPattern(), node.getSubsets(), rewrittenVariableDefinitions);
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), patternRecognitionNode, ImmutableSet.copyOf(node.getOutputSymbols())).orElse(patternRecognitionNode));
}
use of io.trino.sql.planner.plan.PatternRecognitionNode in project trino by trinodb.
the class SymbolMapper method map.
public PatternRecognitionNode map(PatternRecognitionNode node, PlanNode source) {
ImmutableMap.Builder<Symbol, WindowNode.Function> newFunctions = ImmutableMap.builder();
node.getWindowFunctions().forEach((symbol, function) -> {
List<Expression> newArguments = function.getArguments().stream().map(this::map).collect(toImmutableList());
WindowNode.Frame newFrame = map(function.getFrame());
newFunctions.put(map(symbol), new WindowNode.Function(function.getResolvedFunction(), newArguments, newFrame, function.isIgnoreNulls()));
});
ImmutableMap.Builder<Symbol, Measure> newMeasures = ImmutableMap.builder();
node.getMeasures().forEach((symbol, measure) -> {
ExpressionAndValuePointers newExpression = map(measure.getExpressionAndValuePointers());
newMeasures.put(map(symbol), new Measure(newExpression, measure.getType()));
});
ImmutableMap.Builder<IrLabel, ExpressionAndValuePointers> newVariableDefinitions = ImmutableMap.builder();
node.getVariableDefinitions().forEach((label, expression) -> newVariableDefinitions.put(label, map(expression)));
return new PatternRecognitionNode(node.getId(), source, mapAndDistinct(node.getSpecification()), node.getHashSymbol().map(this::map), node.getPrePartitionedInputs().stream().map(this::map).collect(toImmutableSet()), node.getPreSortedOrderPrefix(), newFunctions.buildOrThrow(), newMeasures.buildOrThrow(), node.getCommonBaseFrame().map(this::map), node.getRowsPerMatch(), node.getSkipToLabel(), node.getSkipToPosition(), node.isInitial(), node.getPattern(), node.getSubsets(), newVariableDefinitions.buildOrThrow());
}
use of io.trino.sql.planner.plan.PatternRecognitionNode in project trino by trinodb.
the class QueryPlanner method planPatternRecognition.
private PlanBuilder planPatternRecognition(PlanBuilder subPlan, FunctionCall windowFunction, ResolvedWindow window, PlanAndMappings coercions, Optional<Symbol> frameEndSymbol) {
WindowNode.Specification specification = planWindowSpecification(window.getPartitionBy(), window.getOrderBy(), coercions::get);
// in window frame with pattern recognition, the frame extent is specified as `ROWS BETWEEN CURRENT ROW AND ... `
WindowFrame frame = window.getFrame().orElseThrow();
FrameBound frameEnd = frame.getEnd().orElseThrow();
WindowNode.Frame baseFrame = new WindowNode.Frame(WindowFrame.Type.ROWS, FrameBound.Type.CURRENT_ROW, Optional.empty(), Optional.empty(), frameEnd.getType(), frameEndSymbol, Optional.empty(), Optional.empty(), frameEnd.getValue());
Symbol newSymbol = symbolAllocator.newSymbol(windowFunction, analysis.getType(windowFunction));
NullTreatment nullTreatment = windowFunction.getNullTreatment().orElse(NullTreatment.RESPECT);
WindowNode.Function function = new WindowNode.Function(analysis.getResolvedFunction(windowFunction), windowFunction.getArguments().stream().map(argument -> {
if (argument instanceof LambdaExpression) {
return subPlan.rewrite(argument);
}
return coercions.get(argument).toSymbolReference();
}).collect(toImmutableList()), baseFrame, nullTreatment == NullTreatment.IGNORE);
PatternRecognitionComponents components = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, outerContext, session, recursiveSubqueries).planPatternRecognitionComponents(subPlan::rewrite, frame.getSubsets(), ImmutableList.of(), frame.getAfterMatchSkipTo(), frame.getPatternSearchMode(), frame.getPattern().orElseThrow(), frame.getVariableDefinitions());
// create pattern recognition node
return new PlanBuilder(subPlan.getTranslations().withAdditionalMappings(ImmutableMap.of(scopeAwareKey(windowFunction, analysis, subPlan.getScope()), newSymbol)), new PatternRecognitionNode(idAllocator.getNextId(), subPlan.getRoot(), specification, Optional.empty(), ImmutableSet.of(), 0, ImmutableMap.of(newSymbol, function), components.getMeasures(), Optional.of(baseFrame), RowsPerMatch.WINDOW, components.getSkipToLabel(), components.getSkipToPosition(), components.isInitial(), components.getPattern(), components.getSubsets(), components.getVariableDefinitions()));
}
use of io.trino.sql.planner.plan.PatternRecognitionNode in project trino by trinodb.
the class QueryPlanner method planPatternRecognition.
private PlanBuilder planPatternRecognition(PlanBuilder subPlan, WindowOperation windowMeasure, ResolvedWindow window, Optional<Symbol> frameEndSymbol) {
WindowNode.Specification specification = planWindowSpecification(window.getPartitionBy(), window.getOrderBy(), subPlan::translate);
// in window frame with pattern recognition, the frame extent is specified as `ROWS BETWEEN CURRENT ROW AND ... `
WindowFrame frame = window.getFrame().orElseThrow();
FrameBound frameEnd = frame.getEnd().orElseThrow();
WindowNode.Frame baseFrame = new WindowNode.Frame(WindowFrame.Type.ROWS, FrameBound.Type.CURRENT_ROW, Optional.empty(), Optional.empty(), frameEnd.getType(), frameEndSymbol, Optional.empty(), Optional.empty(), frameEnd.getValue());
PatternRecognitionComponents components = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, outerContext, session, recursiveSubqueries).planPatternRecognitionComponents(subPlan::rewrite, frame.getSubsets(), ImmutableList.of(analysis.getMeasureDefinition(windowMeasure)), frame.getAfterMatchSkipTo(), frame.getPatternSearchMode(), frame.getPattern().orElseThrow(), frame.getVariableDefinitions());
Symbol measureSymbol = getOnlyElement(components.getMeasures().keySet());
// create pattern recognition node
return new PlanBuilder(subPlan.getTranslations().withAdditionalMappings(ImmutableMap.of(scopeAwareKey(windowMeasure, analysis, subPlan.getScope()), measureSymbol)), new PatternRecognitionNode(idAllocator.getNextId(), subPlan.getRoot(), specification, Optional.empty(), ImmutableSet.of(), 0, ImmutableMap.of(), components.getMeasures(), Optional.of(baseFrame), RowsPerMatch.WINDOW, components.getSkipToLabel(), components.getSkipToPosition(), components.isInitial(), components.getPattern(), components.getSubsets(), components.getVariableDefinitions()));
}
use of io.trino.sql.planner.plan.PatternRecognitionNode in project trino by trinodb.
the class WindowFunctionMatcher method getAssignedSymbol.
@Override
public Optional<Symbol> getAssignedSymbol(PlanNode node, Session session, Metadata metadata, SymbolAliases symbolAliases) {
Optional<Symbol> result = Optional.empty();
Map<Symbol, Function> assignments;
if (node instanceof WindowNode) {
assignments = ((WindowNode) node).getWindowFunctions();
} else if (node instanceof PatternRecognitionNode) {
assignments = ((PatternRecognitionNode) node).getWindowFunctions();
} else {
return result;
}
FunctionCall expectedCall = callMaker.getExpectedValue(symbolAliases);
Optional<WindowNode.Frame> expectedFrame = frameMaker.map(maker -> maker.getExpectedValue(symbolAliases));
for (Map.Entry<Symbol, Function> assignment : assignments.entrySet()) {
Function function = assignment.getValue();
boolean signatureMatches = resolvedFunction.map(assignment.getValue().getResolvedFunction()::equals).orElse(true);
if (signatureMatches && windowFunctionMatches(function, expectedCall, expectedFrame)) {
checkState(result.isEmpty(), "Ambiguous function calls in %s", node);
result = Optional.of(assignment.getKey());
}
}
return result;
}
Aggregations