public <S> S capture(Capture<S> capture) { return captures().get(capture); }
@Override public <T> Match<T> matchWith(WithPattern<T> withPattern, Object object, Captures captures) { Function<? super T, Optional<?>> property = withPattern.getProperty().getFunction(); Optional<?> propertyValue = property.apply((T) object); Match<?> propertyMatch = propertyValue .map(value -> match(withPattern.getPattern(), value, captures)) .orElse(Match.empty()); return propertyMatch.map(ignored -> (T) object); }
private <T> Rule.Result transform(PlanNode node, Rule<T> rule, Matcher matcher, Context context) { Rule.Result result; Match<T> match = matcher.match(rule.getPattern(), node); if (match.isEmpty()) { return Rule.Result.empty(); } long duration; try { long start = System.nanoTime(); result = rule.apply(match.value(), match.captures(), ruleContext(context)); duration = System.nanoTime() - start; } catch (RuntimeException e) { stats.recordFailure(rule); throw e; } stats.record(rule, duration, !result.isEmpty()); return result; }
private <T> Rule.Result transform(PlanNode node, Rule<T> rule, Context context) { Capture<T> nodeCapture = newCapture(); Pattern<T> pattern = rule.getPattern().capturedAs(nodeCapture); Iterator<Match> matches = pattern.match(node, context.lookup).iterator(); while (matches.hasNext()) { Match match = matches.next(); long duration; Rule.Result result; try { long start = System.nanoTime(); result = rule.apply(match.capture(nodeCapture), match.captures(), ruleContext(context)); duration = System.nanoTime() - start; } catch (RuntimeException e) { stats.recordFailure(rule); throw e; } stats.record(rule, duration, !result.isEmpty()); if (result.getTransformedPlan().isPresent()) { return result; } } return Rule.Result.empty(); }
@Test public void noMatchMeansNoCaptures() { Capture<Void> impossible = newCapture(); Pattern<Void> pattern = typeOf(Void.class).capturedAs(impossible); Match<Void> match = DefaultMatcher.DEFAULT_MATCHER.match(pattern, 42); assertTrue(match.isEmpty()); Throwable throwable = expectThrows(NoSuchElementException.class, () -> match.capture(impossible)); assertTrue(throwable.getMessage().contains("Captures are undefined for an empty Match")); }
@Override public <T> Match<T> match(Pattern<T> pattern, Object object, Captures captures) { if (pattern.previous() != null) { Match<?> match = match(pattern.previous(), object, captures); return match.flatMap((value) -> pattern.accept(this, value, match.captures())); } else { return pattern.accept(this, object, captures); } }
private <T, R> Match<R> assertMatch(Pattern<R> pattern, T matchedAgainst, R expectedMatch) { Match<R> match = DefaultMatcher.DEFAULT_MATCHER.match(pattern, matchedAgainst); assertEquals(expectedMatch, match.value()); return match; }
@Test public void unknownCaptureIsAnError() { Pattern<?> pattern = any(); Capture<?> unknownCapture = newCapture(); Match<?> match = DefaultMatcher.DEFAULT_MATCHER.match(pattern, 42); Throwable throwable = expectThrows(NoSuchElementException.class, () -> match.capture(unknownCapture)); assertTrue(throwable.getMessage().contains("unknown Capture")); }
private <T> void assertNoMatch(Pattern<T> pattern, Object expectedNoMatch) { Match<T> match = DefaultMatcher.DEFAULT_MATCHER.match(pattern, expectedNoMatch); assertEquals(Match.empty(), match); } }
public static Match of(Captures captures) { return new Match(captures); }
private static <T> RuleApplication applyRule(Rule<T> rule, PlanNode planNode, Rule.Context context) { PlanNodeMatcher matcher = new PlanNodeMatcher(context.getLookup()); Match<T> match = matcher.match(rule.getPattern(), planNode); Rule.Result result; if (!rule.isEnabled(context.getSession()) || match.isEmpty()) { result = Rule.Result.empty(); } else { result = rule.apply(match.value(), match.captures(), context); } return new RuleApplication(context.getLookup(), context.getStatsProvider(), context.getSymbolAllocator().getTypes(), result); }
private static <T> RuleApplication applyRule(Rule<T> rule, PlanNode planNode, Rule.Context context) { Capture<T> planNodeCapture = newCapture(); Pattern<T> pattern = rule.getPattern().capturedAs(planNodeCapture); Optional<Match> match = pattern.match(planNode, context.getLookup()) .collect(toOptional()); Rule.Result result; if (!rule.isEnabled(context.getSession()) || !match.isPresent()) { result = Rule.Result.empty(); } else { result = rule.apply(match.get().capture(planNodeCapture), match.get().captures(), context); } return new RuleApplication(context.getLookup(), context.getStatsProvider(), context.getSymbolAllocator().getTypes(), result); }
@Test public void capturingMatchesInATypesafeManner() { Capture<FilterNode> filter = newCapture(); Capture<ScanNode> scan = newCapture(); Capture<String> name = newCapture(); Pattern<ProjectNode> pattern = project() .with(source().matching(filter().capturedAs(filter) .with(source().matching(scan().capturedAs(scan) .with(tableName().capturedAs(name)))))); ProjectNode tree = new ProjectNode(new FilterNode(new ScanNode("orders"), null)); Match<ProjectNode> match = assertMatch(pattern, tree); //notice the concrete type despite no casts: FilterNode capturedFilter = match.capture(filter); assertEquals(tree.getSource(), capturedFilter); assertEquals(((FilterNode) tree.getSource()).getSource(), match.capture(scan)); assertEquals("orders", match.capture(name)); }
@Override public <T> Match<T> matchWith(WithPattern<T> withPattern, Object object, Captures captures) { Function<? super T, Optional<?>> property = withPattern.getProperty().getFunction(); Optional<?> propertyValue = property.apply((T) object); Optional<?> resolvedValue = propertyValue .map(value -> value instanceof GroupReference ? lookup.resolve(((GroupReference) value)) : value); Match<?> propertyMatch = resolvedValue .map(value -> match(withPattern.getPattern(), value, captures)) .orElse(Match.empty()); return propertyMatch.map(ignored -> (T) object); } }
public <T> T capture(Capture<T> capture) { return captures().get(capture); }
public final <C> Stream<Match> match(Object object, Captures captures, C context) { if (previous.isPresent()) { return previous.get().match(object, captures, context) .flatMap(match -> accept(object, match.captures(), context)); } else { return accept(object, captures, context); } }