use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class InExtractor method adjustOrdering.
/**
* Adjust plan ordering for the result of handling these {@code IN} clauses.
* @param ordering the base plan ordering
* @param asPrefix {@code true} if the {@code IN} conditions become part of an equality prefix (because the elements are merged in order),
* {@code false} if a separate ordering beforehand (because the elements are concatenated in turn)
* @return a new plan ordering
*/
@Nullable
public PlanOrderingKey adjustOrdering(@Nullable PlanOrderingKey ordering, boolean asPrefix) {
if (ordering == null || inClauses.isEmpty()) {
return ordering;
}
// All the ordering keys from the IN joins look like non-prefix ordering and come before the others.
final List<KeyExpression> keys = new ArrayList<>(ordering.getKeys());
int prefixSize = ordering.getPrefixSize();
final int primaryKeyStart = ordering.getPrimaryKeyStart();
final int primaryKeyTailFromEnd = keys.size() - ordering.getPrimaryKeyTail();
for (int i = 0; i < inClauses.size(); i++) {
final KeyExpression inOrdering = inClauses.get(i).orderingKey;
if (inOrdering == null) {
return null;
}
final int position = keys.indexOf(inOrdering);
if (position >= 0) {
if (position < prefixSize) {
// No longer an equality.
prefixSize--;
}
keys.remove(position);
}
keys.add(prefixSize + i, inOrdering);
if (asPrefix) {
prefixSize++;
}
}
return new PlanOrderingKey(keys, prefixSize, primaryKeyStart, keys.size() - primaryKeyTailFromEnd);
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class AvailableFields method fromIndex.
@Nonnull
public static AvailableFields fromIndex(@Nonnull RecordType recordType, @Nonnull Index index, @Nonnull PlannableIndexTypes indexTypes, @Nullable KeyExpression commonPrimaryKey) {
final KeyExpression rootExpression = index.getRootExpression();
final List<KeyExpression> keyFields = new ArrayList<>();
final List<KeyExpression> valueFields = new ArrayList<>();
final List<KeyExpression> nonStoredLuceneExpressions = new ArrayList<>();
if (indexTypes.getTextTypes().contains(index.getType())) {
// Full text index entries have all of their fields except the tokenized one.
keyFields.addAll(TextScanPlanner.getOtherFields(rootExpression));
} else if (indexTypes.getValueTypes().contains(index.getType()) || indexTypes.getRankTypes().contains(index.getType())) {
keyFields.addAll(KeyExpression.getKeyFields(rootExpression));
valueFields.addAll(KeyExpression.getValueFields(rootExpression));
} else if (indexTypes.getLuceneTypes().contains(index.getType())) {
// Todo: this will not take into account stored non-primary-key fields.
nonStoredLuceneExpressions.addAll(rootExpression.normalizeKeyForPositions());
keyFields.addAll(rootExpression.normalizeKeyForPositions());
nonStoredLuceneExpressions.removeAll(recordType.getPrimaryKey().normalizeKeyForPositions());
} else {
// Aggregate index
if (rootExpression instanceof GroupingKeyExpression) {
GroupingKeyExpression groupingKeyExpression = (GroupingKeyExpression) rootExpression;
keyFields.addAll(groupingKeyExpression.getGroupingSubKey().normalizeKeyForPositions());
}
}
// Like FDBRecordStoreBase.indexEntryKey(), but with key expressions instead of actual values.
final List<KeyExpression> primaryKeys = new ArrayList<>(commonPrimaryKey == null ? Collections.emptyList() : commonPrimaryKey.normalizeKeyForPositions());
index.trimPrimaryKey(primaryKeys);
keyFields.addAll(primaryKeys);
Map<KeyExpression, FieldData> fields = new HashMap<>();
final IndexKeyValueToPartialRecord.Builder builder = IndexKeyValueToPartialRecord.newBuilder(recordType);
for (int i = 0; i < keyFields.size(); i++) {
KeyExpression keyField = keyFields.get(i);
FieldData fieldData = FieldData.of(IndexKeyValueToPartialRecord.TupleSource.KEY, i);
if (!nonStoredLuceneExpressions.contains(keyField) && !keyField.createsDuplicates() && addCoveringField(keyField, fieldData, builder)) {
fields.put(keyField, fieldData);
}
}
for (int i = 0; i < valueFields.size(); i++) {
KeyExpression valueField = valueFields.get(i);
FieldData fieldData = FieldData.of(IndexKeyValueToPartialRecord.TupleSource.VALUE, i);
if (!nonStoredLuceneExpressions.contains(valueField) && !valueField.createsDuplicates() && addCoveringField(valueField, fieldData, builder)) {
fields.put(valueField, fieldData);
}
}
if (!builder.isValid()) {
return NO_FIELDS;
}
return new AvailableFields(fields);
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class PlanOrderingKey method isOrderingCompatible.
/**
* Is the given ordering key compatible with the candidate merge key?
* A subkeys of the candidate key can appear in the equals part of the ordering in any order.
* The remainder must match the ordering key after the equality.
*/
private static boolean isOrderingCompatible(@Nonnull PlanOrderingKey planOrderingKey, @Nonnull KeyExpression candidateKey) {
int nextNonPrefix = planOrderingKey.prefixSize;
for (KeyExpression component : candidateKey.normalizeKeyForPositions()) {
int pos = planOrderingKey.keys.indexOf(component);
if (pos < 0) {
// Not present at all.
return false;
}
if (pos < planOrderingKey.prefixSize) {
// ordered by it.
continue;
}
// Otherwise, components need to be in order.
if (pos != nextNonPrefix) {
return false;
}
nextNonPrefix++;
}
return true;
}
use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.
the class StandardIndexMaintainer method evaluateIndex.
/**
* Apply the key and value expressions to a <code>record</code>.
* @param <M> the message type of the record
* @param record the record from which the index will extract its key and value
* @return a list of index keys and values
*/
@Override
public <M extends Message> List<IndexEntry> evaluateIndex(@Nonnull FDBRecord<M> record) {
final KeyExpression rootExpression = state.index.getRootExpression();
final List<Key.Evaluated> indexKeys = rootExpression.evaluate(record);
// so we have to tease them apart.
if (rootExpression instanceof KeyWithValueExpression) {
final KeyWithValueExpression keyWithValueExpression = (KeyWithValueExpression) rootExpression;
return indexKeys.stream().map(key -> new IndexEntry(state.index, keyWithValueExpression.getKey(key), keyWithValueExpression.getValue(key))).collect(Collectors.toList());
}
return indexKeys.stream().map(key -> new IndexEntry(state.index, key)).collect(Collectors.toList());
}
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 ThenKeyExpression thenKeyExpression) {
if (thenKeyExpression.getColumnSize() > 1) {
throw new RecordCoreException("cannot expand ThenKeyExpression in scalar expansion");
}
final ScalarVisitorState state = getCurrentState();
final KeyExpression child = Iterables.getOnlyElement(thenKeyExpression.getChildren());
return pop(child.expand(push(state)));
}
Aggregations