use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method computeIndexFilters.
private ScoredPlan computeIndexFilters(@Nonnull PlanContext planContext, @Nonnull final ScoredPlan plan) {
if (plan.plan instanceof RecordQueryPlanWithIndex) {
final RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) plan.plan;
final Index index = metaData.getIndex(indexPlan.getIndexName());
final Collection<RecordType> recordTypes = metaData.recordTypesForIndex(index);
if (recordTypes.size() != 1) {
return plan;
}
final RecordType recordType = Iterables.getOnlyElement(recordTypes);
final List<QueryComponent> unsatisfiedFilters = new ArrayList<>(plan.unsatisfiedFilters);
final AvailableFields availableFieldsFromIndex = AvailableFields.fromIndex(recordType, index, indexTypes, planContext.commonPrimaryKey);
final List<QueryComponent> indexFilters = Lists.newArrayListWithCapacity(unsatisfiedFilters.size());
final List<QueryComponent> residualFilters = Lists.newArrayListWithCapacity(unsatisfiedFilters.size());
FilterVisitor.partitionFilters(unsatisfiedFilters, availableFieldsFromIndex, indexFilters, residualFilters, null);
if (!indexFilters.isEmpty()) {
return plan.withFilters(residualFilters, indexFilters);
}
}
return plan;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex in project fdb-record-layer by FoundationDB.
the class OrderingProperty method fromIndexScanOrCoveringIndexScan.
@Nonnull
private static Optional<Ordering> fromIndexScanOrCoveringIndexScan(@Nonnull final PlanContext context, @Nonnull final RecordQueryPlan plan) {
final RecordQueryIndexPlan recordQueryIndexPlan;
if (plan instanceof RecordQueryIndexPlan) {
recordQueryIndexPlan = (RecordQueryIndexPlan) plan;
} else if (plan instanceof RecordQueryCoveringIndexPlan) {
final RecordQueryPlanWithIndex planWithIndex = ((RecordQueryCoveringIndexPlan) plan).getIndexPlan();
if (planWithIndex instanceof RecordQueryIndexPlan) {
recordQueryIndexPlan = (RecordQueryIndexPlan) planWithIndex;
} else {
return Optional.empty();
}
} else {
return Optional.empty();
}
final String indexName = recordQueryIndexPlan.getIndexName();
final RecordMetaData metaData = context.getMetaData();
final Index index = metaData.getIndex(indexName);
final Collection<RecordType> recordTypesForIndex = metaData.recordTypesForIndex(index);
final KeyExpression commonPrimaryKeyForIndex = RecordMetaData.commonPrimaryKey(recordTypesForIndex);
final KeyExpression keyExpression = ValueIndexExpansionVisitor.fullKey(index, commonPrimaryKeyForIndex);
final ScanComparisons scanComparisons = recordQueryIndexPlan.getComparisons();
return fromKeyAndScanComparisons(keyExpression, scanComparisons, plan.isReverse(), index.isUnique());
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex in project fdb-record-layer by FoundationDB.
the class RecordQueryPlannerSubstitutionVisitor method availableFields.
@Nonnull
public static AvailableFields availableFields(@Nonnull RecordMetaData recordMetaData, @Nonnull PlannableIndexTypes indexTypes, @Nullable KeyExpression commonPrimaryKey, @Nonnull RecordQueryPlan plan) {
if (plan instanceof RecordQueryPlanWithIndex) {
RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) plan;
Index index = recordMetaData.getIndex(indexPlan.getIndexName());
final Collection<RecordType> recordTypes = recordMetaData.recordTypesForIndex(index);
if (recordTypes.size() != 1) {
return AvailableFields.NO_FIELDS;
}
final RecordType recordType = Iterables.getOnlyElement(recordTypes);
return AvailableFields.fromIndex(recordType, index, indexTypes, commonPrimaryKey);
} else if (plan instanceof RecordQueryFetchFromPartialRecordPlan) {
RecordQueryFetchFromPartialRecordPlan fetchPlan = (RecordQueryFetchFromPartialRecordPlan) plan;
return fetchPlan.getChild().getAvailableFields();
}
return AvailableFields.NO_FIELDS;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex in project fdb-record-layer by FoundationDB.
the class RecordQueryPlannerSubstitutionVisitor method removeIndexFetch.
@Nullable
public static RecordQueryPlan removeIndexFetch(@Nonnull RecordMetaData recordMetaData, @Nonnull PlannableIndexTypes indexTypes, @Nullable KeyExpression commonPrimaryKey, @Nonnull RecordQueryPlan plan, @Nonnull Set<KeyExpression> requiredFields) {
if (plan instanceof RecordQueryPlanWithIndex) {
RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) plan;
Index index = recordMetaData.getIndex(indexPlan.getIndexName());
final Collection<RecordType> recordTypes = recordMetaData.recordTypesForIndex(index);
if (recordTypes.size() != 1) {
return null;
}
final RecordType recordType = Iterables.getOnlyElement(recordTypes);
AvailableFields fieldsFromIndex = AvailableFields.fromIndex(recordType, index, indexTypes, commonPrimaryKey);
Set<KeyExpression> fields = new HashSet<>(requiredFields);
if (commonPrimaryKey != null) {
// Need the primary key, even if it wasn't one of the explicit result fields.
fields.addAll(commonPrimaryKey.normalizeKeyForPositions());
}
if (fieldsFromIndex.containsAll(fields)) {
final IndexKeyValueToPartialRecord keyValueToPartialRecord = fieldsFromIndex.buildIndexKeyValueToPartialRecord(recordType).build();
if (keyValueToPartialRecord != null) {
return new RecordQueryCoveringIndexPlan(indexPlan, recordType.getName(), fieldsFromIndex, keyValueToPartialRecord);
}
}
} else if (plan instanceof RecordQueryFetchFromPartialRecordPlan) {
RecordQueryFetchFromPartialRecordPlan fetchPlan = (RecordQueryFetchFromPartialRecordPlan) plan;
if (fetchPlan.getChild().getAvailableFields().containsAll(requiredFields)) {
return ((RecordQueryFetchFromPartialRecordPlan) plan).getChild();
}
}
return null;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex 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;
}
}
Aggregations