use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class ScalarTranslationVisitor method visitExpression.
@Nonnull
@Override
public Value visitExpression(@Nonnull final NestingKeyExpression nestingKeyExpression) {
final FieldKeyExpression parent = nestingKeyExpression.getParent();
final KeyExpression.FanType fanType = parent.getFanType();
if (fanType != KeyExpression.FanType.None) {
throw new RecordCoreException("cannot expand fan outs in scalar expansion");
}
final ScalarVisitorState state = getCurrentState();
final List<String> fieldNamePrefix = state.getFieldNamePrefix();
final KeyExpression child = nestingKeyExpression.getChild();
final List<String> newPrefix = ImmutableList.<String>builder().addAll(fieldNamePrefix).add(parent.getFieldName()).build();
return pop(child.expand(push(state.withFieldNamePrefix(newPrefix))));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression 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();
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method addRebuildRecordCountsJob.
public void addRebuildRecordCountsJob(List<CompletableFuture<Void>> work) {
final KeyExpression recordCountKey = getRecordMetaData().getRecordCountKey();
if (recordCountKey == null) {
return;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(KeyValueLogMessage.of("recounting all records", subspaceProvider.logKey(), subspaceProvider.toString(context)));
}
final Map<Key.Evaluated, Long> counts = new HashMap<>();
final RecordCursor<FDBStoredRecord<Message>> records = scanRecords(null, ScanProperties.FORWARD_SCAN);
CompletableFuture<Void> future = records.forEach(rec -> {
Key.Evaluated subkey = recordCountKey.evaluateSingleton(rec);
counts.compute(subkey, (k, v) -> (v == null) ? 1 : v + 1);
}).thenApply(vignore -> {
final Transaction tr = ensureContextActive();
final byte[] bytes = new byte[8];
final ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
for (Map.Entry<Key.Evaluated, Long> entry : counts.entrySet()) {
buf.putLong(entry.getValue());
tr.set(getSubspace().pack(Tuple.from(RECORD_COUNT_KEY).addAll(entry.getKey().toTupleAppropriateList())), bytes);
buf.clear();
}
return null;
});
future = context.instrument(FDBStoreTimer.Events.RECOUNT_RECORDS, future);
work.add(future);
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method getSnapshotRecordCount.
@Override
public CompletableFuture<Long> getSnapshotRecordCount(@Nonnull KeyExpression key, @Nonnull Key.Evaluated value, @Nonnull IndexQueryabilityFilter indexQueryabilityFilter) {
if (getRecordMetaData().getRecordCountKey() != null) {
if (key.getColumnSize() != value.size()) {
throw recordCoreException("key and value are not the same size");
}
final ReadTransaction tr = context.readTransaction(true);
final Tuple subkey = Tuple.from(RECORD_COUNT_KEY).addAll(value.toTupleAppropriateList());
if (getRecordMetaData().getRecordCountKey().equals(key)) {
return tr.get(getSubspace().pack(subkey)).thenApply(FDBRecordStore::decodeRecordCount);
} else if (key.isPrefixKey(getRecordMetaData().getRecordCountKey())) {
AsyncIterable<KeyValue> kvs = tr.getRange(getSubspace().range(Tuple.from(RECORD_COUNT_KEY)));
return MoreAsyncUtil.reduce(getExecutor(), kvs.iterator(), 0L, (count, kv) -> count + decodeRecordCount(kv.getValue()));
}
}
return evaluateAggregateFunction(Collections.emptyList(), IndexFunctionHelper.count(key), TupleRange.allOf(value.toTuple()), IsolationLevel.SNAPSHOT, indexQueryabilityFilter).thenApply(tuple -> tuple.getLong(0));
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method saveTypedRecord.
@Nonnull
@API(API.Status.INTERNAL)
protected <M extends Message> CompletableFuture<FDBStoredRecord<M>> saveTypedRecord(@Nonnull RecordSerializer<M> typedSerializer, @Nonnull M rec, @Nonnull RecordExistenceCheck existenceCheck, @Nullable FDBRecordVersion version, @Nonnull VersionstampSaveBehavior behavior) {
final RecordMetaData metaData = metaDataProvider.getRecordMetaData();
final Descriptors.Descriptor recordDescriptor = rec.getDescriptorForType();
final RecordType recordType = metaData.getRecordTypeForDescriptor(recordDescriptor);
final KeyExpression primaryKeyExpression = recordType.getPrimaryKey();
final FDBStoredRecordBuilder<M> recordBuilder = FDBStoredRecord.newBuilder(rec).setRecordType(recordType);
final FDBRecordVersion recordVersion = recordVersionForSave(metaData, version, behavior);
recordBuilder.setVersion(recordVersion);
final Tuple primaryKey = primaryKeyExpression.evaluateSingleton(recordBuilder).toTuple();
recordBuilder.setPrimaryKey(primaryKey);
final CompletableFuture<FDBStoredRecord<M>> result = loadExistingRecord(typedSerializer, primaryKey).thenCompose(oldRecord -> {
if (oldRecord == null) {
if (existenceCheck.errorIfNotExists()) {
throw new RecordDoesNotExistException("record does not exist", LogMessageKeys.PRIMARY_KEY, primaryKey);
}
} else {
if (existenceCheck.errorIfExists()) {
throw new RecordAlreadyExistsException("record already exists", LogMessageKeys.PRIMARY_KEY, primaryKey);
}
if (existenceCheck.errorIfTypeChanged() && oldRecord.getRecordType() != recordType) {
throw new RecordTypeChangedException("record type changed", LogMessageKeys.PRIMARY_KEY, primaryKey, LogMessageKeys.ACTUAL_TYPE, oldRecord.getRecordType().getName(), LogMessageKeys.EXPECTED_TYPE, recordType.getName());
}
}
final FDBStoredRecord<M> newRecord = serializeAndSaveRecord(typedSerializer, recordBuilder, metaData, oldRecord);
if (oldRecord == null) {
addRecordCount(metaData, newRecord, LITTLE_ENDIAN_INT64_ONE);
} else {
if (getTimer() != null) {
getTimer().increment(FDBStoreTimer.Counts.REPLACE_RECORD_VALUE_BYTES, oldRecord.getValueSize());
}
}
return updateSecondaryIndexes(oldRecord, newRecord).thenApply(v -> newRecord);
});
return context.instrument(FDBStoreTimer.Events.SAVE_RECORD, result);
}
Aggregations