public static Pattern<IndexSourceNode> indexSource() { return typeOf(IndexSourceNode.class); }
public Pattern<T> matching(Predicate<? super T> predicate) { return matching((t, context) -> predicate.test(t)); }
@Override public Pattern<ProjectNode> getPattern() { return project() .with(source().matching(targetPattern.capturedAs(targetCapture))); }
@Test public void trivialMatchers() { //any assertMatch(any(), 42); assertMatch(any(), "John Doe"); //class based assertMatch(typeOf(Integer.class), 42); assertMatch(typeOf(Number.class), 42); assertNoMatch(typeOf(Integer.class), "John Doe"); //predicate-based assertMatch(typeOf(Integer.class).matching(x -> x > 0), 42); assertNoMatch(typeOf(Integer.class).matching(x -> x > 0), -1); }
public PropertyPattern<F, C, T> capturedAs(Capture<T> capture) { Pattern<T> matchAll = (Pattern<T>) Pattern.any(); return matching(matchAll.capturedAs(capture)); }
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 propertyMatchers() { Pattern<String> aString = typeOf(String.class); Property<String, Integer> length = Property.property("length", String::length); String string = "a"; assertMatch(aString.with(length.equalTo(1)), string); assertMatch(project().with(source().matching(scan())), new ProjectNode(new ScanNode("T"))); assertMatch(aString.with(length.matching(any())), string); assertMatch(aString.with(length.matching(x -> x > 0)), string); assertMatch(aString.with(length.matching((Number x) -> x.intValue() > 0)), string); assertNoMatch(aString.with(length.equalTo(0)), string); assertNoMatch(project().with(source().matching(scan())), new ProjectNode(new ProjectNode(new ScanNode("T")))); assertNoMatch(aString.with(length.matching(typeOf(Void.class))), string); assertNoMatch(aString.with(length.matching(x -> x < 1)), string); assertNoMatch(aString.with(length.matching((Number x) -> x.intValue() < 1)), string); }
@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")); }
public <C> boolean matches(Object object, C context) { return match(object, context) .findFirst() .isPresent(); }
@Test public void optionalProperties() { Property<RelNode, RelNode> onlySource = Property.optionalProperty("onlySource", node -> Optional.of(node.getSources()) .filter(sources -> sources.size() == 1) .map((List<RelNode> sources) -> sources.get(0))); Pattern<RelNode> relNodeWithExactlyOneSource = plan() .with(onlySource.matching(any())); assertMatch(relNodeWithExactlyOneSource, new ProjectNode(new ScanNode("t"))); assertNoMatch(relNodeWithExactlyOneSource, new ScanNode("t")); assertNoMatch(relNodeWithExactlyOneSource, new JoinNode(new ScanNode("t"), new ScanNode("t"))); }
@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")); }
@Test public void matchNestedProperties() { Pattern<ProjectNode> pattern = project().with(source().matching(scan())); assertMatch(pattern, new ProjectNode(new ScanNode("t"))); assertNoMatch(pattern, new ScanNode("t")); //TODO this needs a custom Option type to work , or NPEs will happen. //Optional does not allow null values. //assertNoMatch(pattern, new ProjectNode(null)); assertNoMatch(pattern, new ProjectNode(new ProjectNode(null))); }
@Override public Pattern<ProjectNode> getPattern() { return project() .with(source().matching(targetPattern.capturedAs(targetCapture))); }
@Test public void testWithPlanNodeHierarchy() { Rule projectRule1 = new NoOpRule(Pattern.typeOf(ProjectNode.class)); Rule projectRule2 = new NoOpRule(Pattern.typeOf(ProjectNode.class)); Rule filterRule = new NoOpRule(Pattern.typeOf(FilterNode.class)); Rule anyRule = new NoOpRule(Pattern.any()); RuleIndex ruleIndex = RuleIndex.builder() .register(projectRule1) .register(projectRule2) .register(filterRule) .register(anyRule) .build(); ProjectNode projectNode = planBuilder.project(Assignments.of(), planBuilder.values()); FilterNode filterNode = planBuilder.filter(BooleanLiteral.TRUE_LITERAL, planBuilder.values()); ValuesNode valuesNode = planBuilder.values(); assertEquals( ruleIndex.getCandidates(projectNode).collect(toSet()), ImmutableSet.of(projectRule1, projectRule2, anyRule)); assertEquals( ruleIndex.getCandidates(filterNode).collect(toSet()), ImmutableSet.of(filterRule, anyRule)); assertEquals( ruleIndex.getCandidates(valuesNode).collect(toSet()), ImmutableSet.of(anyRule)); }