use of com.apple.foundationdb.record.query.plan.AvailableFields 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.AvailableFields in project fdb-record-layer by FoundationDB.
the class FilterVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryFilterPlan) {
final RecordQueryFilterPlan filterPlan = (RecordQueryFilterPlan) recordQueryPlan;
final List<QueryComponent> filters = filterPlan.getFilters();
final AvailableFields availableFields = availableFields(((RecordQueryFilterPlan) recordQueryPlan).getInnerPlan());
// Partition the filters according to whether they can be evaluated using just the fields from the index or
// if they need a full record.
final List<QueryComponent> indexFilters = Lists.newArrayListWithCapacity(filters.size());
final List<QueryComponent> residualFilters = Lists.newArrayListWithCapacity(filters.size());
final Set<KeyExpression> allReferencedFields = new HashSet<>();
partitionFilters(filters, availableFields, indexFilters, residualFilters, allReferencedFields);
Verify.verify(indexFilters.size() + residualFilters.size() == filters.size());
if (indexFilters.isEmpty()) {
return recordQueryPlan;
}
@Nullable RecordQueryPlan removedFetchPlan = removeIndexFetch(filterPlan.getChild(), allReferencedFields);
if (removedFetchPlan == null) {
return recordQueryPlan;
}
recordQueryPlan = new RecordQueryFetchFromPartialRecordPlan(new RecordQueryFilterPlan(removedFetchPlan, indexFilters), TranslateValueFunction.unableToTranslate());
if (!residualFilters.isEmpty()) {
recordQueryPlan = new RecordQueryFilterPlan(recordQueryPlan, residualFilters);
}
}
return recordQueryPlan;
}
Aggregations