use of com.apple.foundationdb.record.metadata.RecordType 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.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class IndexingCommon method fillTargetIndexers.
private void fillTargetIndexers(@Nonnull List<Index> targetIndexes, @Nullable Collection<RecordType> recordTypes) {
boolean presetTypes = false;
if (recordTypes != null) {
if (targetIndexes.size() > 1) {
throw new IndexingBase.ValidationException("Can't use preset record types with multi target indexing");
}
presetTypes = true;
}
if (recordStoreBuilder.getMetaDataProvider() == null) {
throw new MetaDataException("record store builder must include metadata");
}
final RecordMetaData metaData = recordStoreBuilder.getMetaDataProvider().getRecordMetaData();
for (Index targetIndex : targetIndexes) {
Collection<RecordType> types;
if (presetTypes) {
types = recordTypes;
} else {
types = metaData.recordTypesForIndex(targetIndex);
}
boolean isSynthetic = false;
if (types.stream().anyMatch(RecordType::isSynthetic)) {
types = new SyntheticRecordPlanner(metaData, new RecordStoreState(null, null)).storedRecordTypesForIndex(targetIndex, types);
isSynthetic = true;
}
targetIndexContexts.add(new IndexContext(targetIndex, types, isSynthetic));
allRecordTypes.addAll(types);
}
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class SyntheticRecordPlanner method forIndex.
/**
* Construct a plan for generating synthetic records for a given index.
*
* The generated records will be of indexed record types.
*
* Used by the {@link com.apple.foundationdb.record.provider.foundationdb.OnlineIndexer} to build from a full scan of stored records.
* @param index an index on synthetic record types
* @return a plan that can be applied to scanned records to generate synthetic records
*/
@Nonnull
public SyntheticRecordFromStoredRecordPlan forIndex(@Nonnull Index index) {
final Collection<RecordType> recordTypes = recordMetaData.recordTypesForIndex(index);
if (recordTypes.size() == 1) {
final RecordType recordType = recordTypes.iterator().next();
if (!recordType.isSynthetic()) {
throw new RecordCoreException("Index does not apply to synthetic record types " + index);
}
return forType((SyntheticRecordType<?>) recordType);
}
Multimap<String, SyntheticRecordFromStoredRecordPlan> byType = ArrayListMultimap.create();
for (RecordType recordType : recordTypes) {
if (!(recordType instanceof JoinedRecordType)) {
throw unknownSyntheticType(recordType);
}
JoinedRecordType joinedRecordType = (JoinedRecordType) recordType;
Optional<JoinedRecordType.JoinConstituent> maybeConstituent = joinedRecordType.getConstituents().stream().filter(c -> !c.isOuterJoined()).findFirst();
if (maybeConstituent.isPresent()) {
addToByType(byType, joinedRecordType, maybeConstituent.get());
} else {
for (JoinedRecordType.JoinConstituent joinConstituent : joinedRecordType.getConstituents()) {
addToByType(byType, joinedRecordType, joinConstituent);
}
}
}
return createByType(byType);
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class SyntheticRecordPlanner method storedRecordTypesForIndex.
/**
* Determine what stored record types would be need to scanned in order to rebuild a given index.
*
* From those scans, queries will be executed to load other record types to complete the synthesis.
* <p>
* In cases such as full outer join, there is no single record type from which all joins can be produced.
* @param index the index that needs to be built
* @param recordTypes a subset of the index's record types or {@code null} for all
* @return a set of stored record types that are sufficient to generate the synthesized records for the index
*/
public Set<RecordType> storedRecordTypesForIndex(@Nonnull Index index, @Nullable Collection<RecordType> recordTypes) {
if (recordTypes == null) {
recordTypes = recordMetaData.recordTypesForIndex(index);
}
Set<RecordType> result = new HashSet<>();
for (RecordType recordType : recordTypes) {
if (!(recordType instanceof JoinedRecordType)) {
throw unknownSyntheticType(recordType);
}
JoinedRecordType joinedRecordType = (JoinedRecordType) recordType;
Optional<JoinedRecordType.JoinConstituent> maybeConstituent = joinedRecordType.getConstituents().stream().filter(c -> !c.isOuterJoined()).findFirst();
if (maybeConstituent.isPresent()) {
result.add(maybeConstituent.get().getRecordType());
} else {
for (JoinedRecordType.JoinConstituent joinConstituent : joinedRecordType.getConstituents()) {
result.add(joinConstituent.getRecordType());
}
}
}
return result;
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class MatchCandidate method fromIndexDefinition.
@Nonnull
static Optional<MatchCandidate> fromIndexDefinition(@Nonnull final RecordMetaData metaData, @Nonnull final Index index, final boolean isReverse) {
final Collection<RecordType> recordTypesForIndex = metaData.recordTypesForIndex(index);
final KeyExpression commonPrimaryKeyForIndex = RecordMetaData.commonPrimaryKey(recordTypesForIndex);
final ImmutableSet<String> recordTypeNamesForIndex = recordTypesForIndex.stream().map(RecordType::getName).collect(ImmutableSet.toImmutableSet());
final Set<String> availableRecordTypes = metaData.getRecordTypes().keySet();
final String type = index.getType();
if (type.equals(IndexTypes.VALUE)) {
final Quantifier.ForEach baseQuantifier = createBaseQuantifier(availableRecordTypes, recordTypeNamesForIndex);
final ValueIndexExpansionVisitor expansionVisitor = new ValueIndexExpansionVisitor(index, recordTypesForIndex);
try {
return Optional.of(expansionVisitor.expand(baseQuantifier, commonPrimaryKeyForIndex, isReverse));
} catch (final UnsupportedOperationException uOE) {
// just log and return empty
if (LOGGER.isDebugEnabled()) {
final String message = KeyValueLogMessage.of("unsupported value index", "reason", uOE.getMessage(), "indexName", index.getName());
LOGGER.debug(message, uOE);
}
}
}
return Optional.empty();
}
Aggregations