use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method planVersion.
@Nullable
private ScoredPlan planVersion(@Nonnull CandidateScan candidateScan, @Nonnull KeyExpression indexExpr, @Nonnull QueryRecordFunctionWithComparison filter, @Nullable KeyExpression sort) {
if (indexExpr instanceof VersionKeyExpression) {
final Comparisons.Comparison comparison = filter.getComparison();
final ScanComparisons comparisons = ScanComparisons.from(comparison);
if (sort == null || sort.equals(VersionKeyExpression.VERSION)) {
IndexScanParameters scanParameters = IndexScanComparisons.byValue(comparisons);
RecordQueryPlan plan = new RecordQueryIndexPlan(candidateScan.index.getName(), scanParameters, candidateScan.reverse);
return new ScoredPlan(1, plan, Collections.emptyList(), false);
}
} else if (indexExpr instanceof ThenKeyExpression) {
ThenKeyExpression then = (ThenKeyExpression) indexExpr;
if (sort == null) {
// && !then.createsDuplicates()) {
return planVersion(candidateScan, then.getChildren().get(0), filter, null);
} else {
return new AndWithThenPlanner(candidateScan, then, Collections.singletonList(filter), sort).plan();
}
}
return null;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.
the class PlanOrderingKey method forPlan.
@Nullable
public static PlanOrderingKey forPlan(@Nonnull RecordMetaData metaData, @Nonnull RecordQueryPlan queryPlan, @Nullable KeyExpression primaryKey) {
if (primaryKey == null) {
return null;
}
while (queryPlan instanceof RecordQueryFilterPlan) {
queryPlan = ((RecordQueryFilterPlan) queryPlan).getInnerPlan();
}
if (queryPlan instanceof RecordQueryPlanWithIndex) {
final RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) queryPlan;
final Index index = metaData.getIndex(indexPlan.getIndexName());
final List<KeyExpression> keys = new ArrayList<>(index.getRootExpression().normalizeKeyForPositions());
int pkeyStart = keys.size();
int pKeyTail = pkeyStart;
// Primary keys come after index value keys, unless they were already part of it.
for (KeyExpression pkey : primaryKey.normalizeKeyForPositions()) {
int pos = keys.indexOf(pkey);
if (pos < 0) {
keys.add(pkey);
} else if (pkeyStart > pos) {
pkeyStart = pos;
}
}
final int prefixSize;
if (indexPlan instanceof RecordQueryIndexPlan) {
prefixSize = ((RecordQueryIndexPlan) indexPlan).getComparisons().getEqualitySize();
} else if (indexPlan instanceof RecordQueryTextIndexPlan) {
final TextScan textScan = ((RecordQueryTextIndexPlan) indexPlan).getTextScan();
int groupingSize = textScan.getGroupingComparisons() != null ? textScan.getGroupingComparisons().getEqualitySize() : 0;
int suffixSize = textScan.getSuffixComparisons() != null ? textScan.getSuffixComparisons().getEqualitySize() : 0;
if (textScan.getTextComparison().getType().isEquality()) {
// Can use the equality comparisons in the grouping columns and any columns after the text index
// plus the text column itself.
prefixSize = groupingSize + suffixSize + 1;
} else {
// by the token that the prefix scan just so happened to hit.
return null;
}
} else {
// Some unknown index plan. Maybe this should throw an error?
return null;
}
return new PlanOrderingKey(keys, prefixSize, pkeyStart, pKeyTail);
} else if (queryPlan instanceof RecordQueryScanPlan) {
final RecordQueryScanPlan scanPlan = (RecordQueryScanPlan) queryPlan;
return new PlanOrderingKey(primaryKey.normalizeKeyForPositions(), scanPlan.getComparisons().getEqualitySize(), 0, 0);
} else if (queryPlan instanceof RecordQueryIntersectionPlan) {
return forComparisonKey(((RecordQueryIntersectionPlan) queryPlan).getComparisonKey(), primaryKey);
} else if (queryPlan instanceof RecordQueryUnionPlan) {
return forComparisonKey(((RecordQueryUnionPlan) queryPlan).getComparisonKey(), primaryKey);
} else {
return null;
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.
the class ValueIndexScanMatchCandidate method tryFetchCoveringIndexScan.
@Nonnull
private Optional<RelationalExpression> tryFetchCoveringIndexScan(@Nonnull final PartialMatch partialMatch, @Nonnull final List<ComparisonRange> comparisonRanges, final boolean isReverse) {
if (recordTypes.size() > 1) {
return Optional.empty();
}
final RecordType recordType = Iterables.getOnlyElement(recordTypes);
final IndexKeyValueToPartialRecord.Builder builder = IndexKeyValueToPartialRecord.newBuilder(recordType);
for (int i = 0; i < indexKeyValues.size(); i++) {
final Value keyValue = indexKeyValues.get(i);
if (keyValue instanceof FieldValue && keyValue.isFunctionallyDependentOn(recordValue)) {
final AvailableFields.FieldData fieldData = AvailableFields.FieldData.of(IndexKeyValueToPartialRecord.TupleSource.KEY, i);
addCoveringField(builder, (FieldValue) keyValue, fieldData);
}
}
for (int i = 0; i < indexValueValues.size(); i++) {
final Value valueValue = indexValueValues.get(i);
if (valueValue instanceof FieldValue && valueValue.isFunctionallyDependentOn(recordValue)) {
final AvailableFields.FieldData fieldData = AvailableFields.FieldData.of(IndexKeyValueToPartialRecord.TupleSource.VALUE, i);
addCoveringField(builder, (FieldValue) valueValue, fieldData);
}
}
if (!builder.isValid()) {
return Optional.empty();
}
final IndexScanParameters scanParameters = IndexScanComparisons.byValue(toScanComparisons(comparisonRanges));
final RecordQueryPlanWithIndex indexPlan = new RecordQueryIndexPlan(index.getName(), scanParameters, isReverse, false, (ValueIndexScanMatchCandidate) partialMatch.getMatchCandidate());
final RecordQueryCoveringIndexPlan coveringIndexPlan = new RecordQueryCoveringIndexPlan(indexPlan, recordType.getName(), // not used except for old planner properties
AvailableFields.NO_FIELDS, builder.build());
return Optional.of(new RecordQueryFetchFromPartialRecordPlan(coveringIndexPlan, coveringIndexPlan::pushValueThroughFetch));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.
the class MergeFetchIntoCoveringIndexRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final RecordQueryIndexPlan innerPlan = call.get(innerPlanMatcher);
call.yield(call.ref(innerPlan));
}
Aggregations