use of com.apple.foundationdb.record.TupleRange in project fdb-record-layer by FoundationDB.
the class RecordQueryScanPlan method rewritePlannerGraph.
/**
* Rewrite the planner graph for better visualization of a query scan plan.
* @param childGraphs planner graphs of children expression that already have been computed
* @return the rewritten planner graph that models scanned storage as a separate node that is connected to the
* actual scan plan node.
*/
@Nonnull
@Override
public PlannerGraph rewritePlannerGraph(@Nonnull List<? extends PlannerGraph> childGraphs) {
Verify.verify(childGraphs.isEmpty());
@Nullable final TupleRange tupleRange = comparisons.toTupleRangeWithoutContext();
final ImmutableList.Builder<String> detailsBuilder = ImmutableList.builder();
final ImmutableMap.Builder<String, Attribute> additionalAttributes = ImmutableMap.builder();
if (tupleRange != null) {
detailsBuilder.add("range: " + tupleRange.getLowEndpoint().toString(false) + "{{low}}, {{high}}" + tupleRange.getHighEndpoint().toString(true));
additionalAttributes.put("low", Attribute.gml(tupleRange.getLow() == null ? "-∞" : tupleRange.getLow().toString()));
additionalAttributes.put("high", Attribute.gml(tupleRange.getHigh() == null ? "∞" : tupleRange.getHigh().toString()));
} else {
detailsBuilder.add("comparisons: {{comparisons}}");
additionalAttributes.put("comparisons", Attribute.gml(comparisons.toString()));
}
if (reverse) {
detailsBuilder.add("direction: {{direction}}");
additionalAttributes.put("direction", Attribute.gml("reversed"));
}
final PlannerGraph.DataNodeWithInfo dataNodeWithInfo;
if (getRecordTypes() == null) {
dataNodeWithInfo = new PlannerGraph.DataNodeWithInfo(NodeInfo.BASE_DATA, ImmutableList.of("ALL"));
} else {
dataNodeWithInfo = new PlannerGraph.DataNodeWithInfo(NodeInfo.BASE_DATA, ImmutableList.of("record types: {{types}}"), ImmutableMap.of("types", Attribute.gml(getRecordTypes().stream().map(Attribute::gml).collect(ImmutableList.toImmutableList()))));
}
return PlannerGraph.fromNodeAndChildGraphs(new PlannerGraph.OperatorNodeWithInfo(this, NodeInfo.SCAN_OPERATOR, detailsBuilder.build(), additionalAttributes.build()), ImmutableList.of(PlannerGraph.fromNodeAndChildGraphs(dataNodeWithInfo, childGraphs)));
}
use of com.apple.foundationdb.record.TupleRange in project fdb-record-layer by FoundationDB.
the class RankedSetIndexHelper method rankRangeToScoreRange.
@Nonnull
public static CompletableFuture<TupleRange> rankRangeToScoreRange(@Nonnull IndexMaintainerState state, int groupPrefixSize, @Nonnull Subspace rankSubspace, @Nonnull RankedSet.Config config, @Nonnull TupleRange rankRange) {
final Tuple prefix = groupPrefix(groupPrefixSize, rankRange, rankSubspace);
if (prefix != null) {
rankSubspace = rankSubspace.subspace(prefix);
}
// Map low and high ranks to scores and scan main index with those.
Number lowRankNum = extractRank(groupPrefixSize, rankRange.getLow());
boolean startFromBeginning = lowRankNum == null || lowRankNum.longValue() < 0L;
EndpointType lowEndpoint = startFromBeginning ? EndpointType.RANGE_INCLUSIVE : rankRange.getLowEndpoint();
Number highRankNum = extractRank(groupPrefixSize, rankRange.getHigh());
EndpointType highEndpoint = rankRange.getHighEndpoint();
if (highRankNum != null && (highRankNum.longValue() < 0L || highEndpoint == EndpointType.RANGE_EXCLUSIVE && highRankNum.longValue() == 0L)) {
// This range is below 0, so we know the range is empty without having to look.
return CompletableFuture.completedFuture(null);
}
if (highRankNum != null && highEndpoint == EndpointType.RANGE_EXCLUSIVE && lowEndpoint == EndpointType.RANGE_EXCLUSIVE && highRankNum.equals(lowRankNum)) {
// This range is exclusively empty.
return CompletableFuture.completedFuture(null);
}
if (startFromBeginning && highRankNum == null) {
// Scanning whole range, no need to convert any ranks.
return CompletableFuture.completedFuture(TupleRange.allOf(prefix));
}
final RankedSet rankedSet = new InstrumentedRankedSet(state, rankSubspace, config);
return init(state, rankedSet).thenCompose(v -> {
CompletableFuture<Tuple> lowScoreFuture = scoreForRank(state, rankedSet, startFromBeginning ? 0L : lowRankNum, null);
CompletableFuture<Tuple> highScoreFuture = scoreForRank(state, rankedSet, highRankNum, null);
return lowScoreFuture.thenCombine(highScoreFuture, (lowScore, highScore) -> {
// from low until the end.
if (lowScore == null) {
return null;
}
EndpointType adjustedHighEndpoint = highScore != null ? highEndpoint : prefix != null ? EndpointType.RANGE_INCLUSIVE : EndpointType.TREE_END;
TupleRange scoreRange = new TupleRange(lowScore, highScore, lowEndpoint, adjustedHighEndpoint);
if (prefix != null) {
scoreRange = scoreRange.prepend(prefix);
}
return scoreRange;
});
});
}
use of com.apple.foundationdb.record.TupleRange in project fdb-record-layer by FoundationDB.
the class TimeWindowLeaderboardIndexMaintainer method negateScoreRange.
/**
* Negate the score part of the given range, which is after the group prefix and before the timestamp and any
* other tiebreakers.
* @param range the range of scores in normal order
* @return a range with scores negated so that they sort in reverse order
*/
protected TupleRange negateScoreRange(@Nonnull TupleRange range) {
final int groupPrefixSize = getGroupingCount();
Tuple low = range.getLow();
Tuple high = range.getHigh();
EndpointType lowEndpoint = range.getLowEndpoint();
EndpointType highEndpoint = range.getHighEndpoint();
if (low == null || low.size() < groupPrefixSize) {
if (lowEndpoint == EndpointType.TREE_START) {
lowEndpoint = EndpointType.TREE_END;
}
} else {
low = negateScoreForHighScoreFirst(low, groupPrefixSize);
}
if (high == null || high.size() < groupPrefixSize) {
if (lowEndpoint == EndpointType.TREE_END) {
lowEndpoint = EndpointType.TREE_START;
}
} else {
high = negateScoreForHighScoreFirst(high, groupPrefixSize);
}
return new TupleRange(high, low, highEndpoint, lowEndpoint);
}
Aggregations