use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class LuceneIndexMaintainer method update.
@Nonnull
@Override
public <M extends Message> CompletableFuture<Void> update(@Nullable FDBIndexableRecord<M> oldRecord, @Nullable FDBIndexableRecord<M> newRecord) {
LOG.trace("update oldRecord={}, newRecord={}", oldRecord, newRecord);
// Extract information for grouping from old and new records
final KeyExpression root = state.index.getRootExpression();
final Map<Tuple, List<LuceneDocumentFromRecord.DocumentField>> oldRecordFields = LuceneDocumentFromRecord.getRecordFields(root, oldRecord);
final Map<Tuple, List<LuceneDocumentFromRecord.DocumentField>> newRecordFields = LuceneDocumentFromRecord.getRecordFields(root, newRecord);
final Set<Tuple> unchanged = new HashSet<>();
for (Map.Entry<Tuple, List<LuceneDocumentFromRecord.DocumentField>> entry : oldRecordFields.entrySet()) {
if (entry.getValue().equals(newRecordFields.get(entry.getKey()))) {
unchanged.add(entry.getKey());
}
}
for (Tuple t : unchanged) {
newRecordFields.remove(t);
oldRecordFields.remove(t);
}
LOG.trace("update oldFields={}, newFields{}", oldRecordFields, newRecordFields);
// delete old
try {
for (Tuple t : oldRecordFields.keySet()) {
deleteDocument(t, oldRecord.getPrimaryKey().pack());
}
} catch (IOException e) {
throw new RecordCoreException("Issue deleting old index keys", "oldRecord", oldRecord, e);
}
// There's actually no possibility of a NPE here. (line 304/306)
if (newRecord == null) {
return AsyncUtil.DONE;
}
// update new
try {
for (Map.Entry<Tuple, List<LuceneDocumentFromRecord.DocumentField>> entry : newRecordFields.entrySet()) {
writeDocument(entry.getValue(), entry.getKey(), newRecord.getPrimaryKey().pack());
}
} catch (IOException e) {
throw new RecordCoreException("Issue updating new index keys", e).addLogInfo("newRecord", newRecord);
}
return AsyncUtil.DONE;
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class FDBComparatorPlanTest method testRepeatedKeyFails.
@DualPlannerTest
void testRepeatedKeyFails() throws Exception {
// Test when the comparison key is a repeated field
complexQuerySetup(NO_HOOK);
RecordQuery query1 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_2").equalsValue(1)).build();
RecordQuery query2 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_2").equalsValue(1)).build();
Descriptors.FieldDescriptor comparisonKey = recordStore.getRecordMetaData().getRecordType("MySimpleRecord").getDescriptor().findFieldByName("repeater");
KeyExpression keyExpression = Key.Expressions.fromDescriptor(comparisonKey);
RecordQueryPlan planUnderTest = RecordQueryComparatorPlan.from(plan(query1, query2), keyExpression, 0, abortOnComparisonFailure);
// Repeated keys will fail the comparison since they are not supported
assertDifferentPlans(planUnderTest, 1, 134, 33);
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class RemoveSortRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final LogicalSortExpression sortExpression = call.get(root);
final RecordQueryPlan innerPlan = call.get(innerPlanMatcher);
final KeyExpression sortKeyExpression = sortExpression.getSort();
if (sortKeyExpression == null) {
call.yield(call.ref(innerPlan));
return;
}
final Optional<Ordering> orderingOptional = OrderingProperty.evaluate(innerPlan, call.getContext());
if (orderingOptional.isEmpty()) {
return;
}
final Ordering ordering = orderingOptional.get();
final Set<KeyExpression> equalityBoundKeys = ordering.getEqualityBoundKeys();
int equalityBoundUnsorted = equalityBoundKeys.size();
final List<KeyPart> orderingKeys = ordering.getOrderingKeyParts();
final Iterator<KeyPart> orderingKeysIterator = orderingKeys.iterator();
final List<KeyExpression> normalizedSortExpressions = sortKeyExpression.normalizeKeyForPositions();
for (final KeyExpression normalizedSortExpression : normalizedSortExpressions) {
if (equalityBoundKeys.contains(normalizedSortExpression)) {
equalityBoundUnsorted--;
continue;
}
if (!orderingKeysIterator.hasNext()) {
return;
}
final KeyPart currentOrderingKeyPart = orderingKeysIterator.next();
if (!normalizedSortExpression.equals(currentOrderingKeyPart.getNormalizedKeyExpression())) {
return;
}
}
final boolean strictOrdered = // If we have exhausted the ordering info's keys, too, then its constituents are strictly ordered.
!orderingKeysIterator.hasNext() || // Also a unique index if have gone through declared fields.
strictlyOrderedIfUnique(innerPlan, call.getContext()::getIndexByName, normalizedSortExpressions.size() + equalityBoundUnsorted);
call.yield(call.ref(strictOrdered ? innerPlan.strictlySorted() : innerPlan));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression 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;
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class IntersectionVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull final RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryIntersectionPlan) {
RecordQueryIntersectionPlan intersectionPlan = (RecordQueryIntersectionPlan) recordQueryPlan;
Set<KeyExpression> requiredFields = intersectionPlan.getRequiredFields();
List<RecordQueryPlan> newChildren = new ArrayList<>(intersectionPlan.getChildren().size());
for (RecordQueryPlan plan : intersectionPlan.getChildren()) {
@Nullable RecordQueryPlan newPlan = removeIndexFetch(plan, requiredFields);
if (newPlan == null) {
// can't remove index fetch, so give up
return recordQueryPlan;
}
newChildren.add(newPlan);
}
return new RecordQueryFetchFromPartialRecordPlan(RecordQueryIntersectionPlan.from(newChildren, intersectionPlan.getComparisonKey()), TranslateValueFunction.unableToTranslate());
}
return recordQueryPlan;
}
Aggregations