use of com.apple.foundationdb.record.Bindings in project fdb-record-layer by FoundationDB.
the class ParameterRelationshipGraph method fromRecordQueryAndBindings.
/**
* Derive a relationship graph from a {@link RecordQuery} and a set of pre-bound parameters in handing in
* as a {@link Bindings} object.
* <p>
* Note that we do not derive additional relationships (yet). So for instance a query
* </p>
* <p>
* {@code
* ...
* WHERE x < $p1 AND x = $p2 AND y < $p2 AND y = $p3
* }
* </p>
* with pre-bindings {@code p1 -> 10, p2 -> 10, p3 -> 10} would result in a graph containing
* <p>
* {@code
* p1 EQUALS p1
* p1 EQUALS p2
* p2 EQUALS p1
* p2 EQUALS p2
* p2 EQUALS p3
* p3 EQUALS p2
* p3 EQUALS p3
* }
* </p>
* but it would not contain
* <p>
* {@code
* p1 EQUALS p3
* p3 EQUALS p1
* }
* </p>
* @param recordQuery query
* @param preBoundParameterBindings parameter bindings already known at planning time
* @return a new {@link ParameterRelationshipGraph}
*/
@Nonnull
public static ParameterRelationshipGraph fromRecordQueryAndBindings(@Nonnull final RecordQuery recordQuery, @Nonnull final Bindings preBoundParameterBindings) {
final QueryComponent filter = recordQuery.getFilter();
final ImmutableNetwork.Builder<String, Relationship> networkBuilder = NetworkBuilder.directed().allowsSelfLoops(true).allowsParallelEdges(true).immutable();
if (filter != null) {
groupedComparisons(filter).flatMap(entry -> StreamSupport.stream(crossProduct(ImmutableList.of(entry.getValue(), entry.getValue())).spliterator(), false)).map(list -> Pair.of(list.get(0), list.get(1))).forEach(pair -> {
final Comparisons.ComparisonWithParameter left = pair.getLeft();
final Comparisons.ComparisonWithParameter right = pair.getRight();
if (left.getParameter().equals(right.getParameter())) {
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
} else if (// It is possible that some of the parameters are not pre-bound. That's not an error,
preBoundParameterBindings.containsBinding(left.getParameter()) && preBoundParameterBindings.containsBinding(right.getParameter())) {
// it just means we cannot establish any sort of relationship between them.
final Object leftComparand = preBoundParameterBindings.get(left.getParameter());
final Object rightComparand = preBoundParameterBindings.get(right.getParameter());
if (Objects.equals(leftComparand, rightComparand)) {
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
}
}
});
}
return new ParameterRelationshipGraph(networkBuilder.build());
}
Aggregations