Repository navigation
Build a match candidate from an index defined on an unnested record type #4641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: apple/g31pranjal/unnested/explode-ordinality-matching
Are you sure you want to change the base?
Changes from all commits
883f137
71e6b67
21a68cc
71b29ee
1f8f04a
8dba6e2
4d26935
b5b5d6b
7594200
86e0145
d3d906f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,8 @@ | |
| import com.apple.foundationdb.record.query.plan.cascades.typing.Type; | ||
| import com.apple.foundationdb.record.query.plan.cascades.values.EmptyValue; | ||
| import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue; | ||
| import com.apple.foundationdb.record.query.plan.cascades.values.QuantifiedObjectValue; | ||
| import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue; | ||
| import com.apple.foundationdb.record.query.plan.cascades.values.Value; | ||
| import com.apple.foundationdb.record.util.ProtoUtils; | ||
| import com.google.common.collect.ImmutableList; | ||
|
|
@@ -206,7 +207,21 @@ | |
| @Nonnull | ||
| @Override | ||
| public Value visitExpression(@Nonnull final ListKeyExpression listKeyExpression) { | ||
| throw new UnsupportedOperationException("visitor method for this key expression is not implemented"); | ||
| if (listKeyExpression.getColumnSize() > 1) { | ||
| throw new RecordCoreException("cannot expand ListKeyExpression in scalar expansion"); | ||
| } | ||
|
Comment on lines
+210
to
+212
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this restriction? (Could use some explanation in a comment.) |
||
|
|
||
| final ScalarVisitorState state = getCurrentState(); | ||
| final KeyExpression child = Iterables.getOnlyElement(listKeyExpression.getChildren()); | ||
|
|
||
| // The child occupies a single position whose value is the nested tuple of the child's own columns, so it is a | ||
| // record of their values -- a record of one for a single-column child, as that tuple is nested all the same. | ||
| final List<KeyExpression> positions = child.normalizeKeyForPositions(); | ||
| final ImmutableList.Builder<Value> valuesBuilder = ImmutableList.builder(); | ||
| for (final KeyExpression position : positions) { | ||
| valuesBuilder.add(pop(position.expand(push(state)))); | ||
| } | ||
| return RecordConstructorValue.ofUnnamed(valuesBuilder.build()); | ||
| } | ||
|
|
||
| @Nonnull | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,18 +149,21 @@ | |
| final var logicalKeyValuesBuilder = ImmutableList.<Value>builder(); | ||
| for (int i = 0; i < indexKeyValues.size(); i++) { | ||
| final Value keyValue = indexKeyValues.get(i); | ||
|
|
||
| final var extractFromIndexEntryPairOptional = | ||
| keyValue.extractFromIndexEntryMaybe(baseObjectValue, EvaluationContext.empty(), AliasMap.emptyMap(), | ||
| ImmutableSet.of(), IndexKeyValueToPartialRecord.TupleSource.KEY, ImmutableIntArray.of(i)); | ||
| if (extractFromIndexEntryPairOptional.isPresent()) { | ||
| final var extractFromIndexEntryPair = extractFromIndexEntryPairOptional.get(); | ||
| if (!addCoveringField(builder, extractFromIndexEntryPair.getKey(), | ||
| extractFromIndexEntryPair.getValue())) { | ||
| return Optional.empty(); | ||
| for (final var datum : entryData(keyValue, ImmutableIntArray.of(i))) { | ||
| final var extractFromIndexEntryPairOptional = | ||
| datum.getLeft().extractFromIndexEntryMaybe(baseObjectValue, EvaluationContext.empty(), | ||
| AliasMap.emptyMap(), ImmutableSet.of(), | ||
| IndexKeyValueToPartialRecord.TupleSource.KEY, datum.getRight()); | ||
| if (extractFromIndexEntryPairOptional.isPresent()) { | ||
| final var extractFromIndexEntryPair = extractFromIndexEntryPairOptional.get(); | ||
| if (!addCoveringField(builder, extractFromIndexEntryPair.getKey(), | ||
| extractFromIndexEntryPair.getValue())) { | ||
| return Optional.empty(); | ||
| } | ||
| recordCoveredField(covered, extractFromIndexEntryPair); | ||
| logicalKeyValuesBuilder.add(extractFromIndexEntryPair.getLeft()); | ||
| } | ||
| recordCoveredField(covered, extractFromIndexEntryPair); | ||
| logicalKeyValuesBuilder.add(extractFromIndexEntryPair.getLeft()); | ||
| } | ||
| } | ||
|
|
||
|
Comment on lines
150
to
169
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find that this logic is now getting quite cumbersome overall, with the two nested loops, the hidden recursion in Could you try spending some time simplifying this further. There’s probably a better way to cut this than the ... and move the recursion, as well as the various |
||
|
|
@@ -192,6 +195,27 @@ | |
| indexEntryToRecordValue(baseType, covered))); | ||
| } | ||
|
|
||
| /** | ||
| * Decomposes one column of the index entry into the data it holds that can be read individually. | ||
| * | ||
| * @param value the value registered for the column | ||
| * @param ordinalPath the path to the column | ||
| * @return the data that column holds, each datum paired with the path at which it sits in the entry's tuple | ||
| */ | ||
| @Nonnull | ||
| private static List<NonnullPair<Value, ImmutableIntArray>> entryData(@Nonnull final Value value, | ||
| @Nonnull final ImmutableIntArray ordinalPath) { | ||
| if (!(value instanceof RecordConstructorValue)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you perhaps add a brief comment (or extend the javadoc) explaining why |
||
| return ImmutableList.of(NonnullPair.of(value, ordinalPath)); | ||
|
Check warning on line 209 in fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/ScanWithFetchMatchCandidate.java
|
||
| } | ||
| final var columns = ((RecordConstructorValue)value).getColumns(); | ||
| final var dataBuilder = ImmutableList.<NonnullPair<Value, ImmutableIntArray>>builder(); | ||
| for (int i = 0; i < columns.size(); i++) { | ||
| dataBuilder.addAll(entryData(columns.get(i).getValue(), ImmutableIntArray.builder().addAll(ordinalPath).add(i).build())); | ||
| } | ||
| return dataBuilder.build(); | ||
| } | ||
|
|
||
| /** | ||
| * Records what the given extraction covers, descending a node per field of the path it fills, which may run into | ||
| * nested messages. Every name is present here, {@code addCoveringField} having already refused the extraction | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These four nested
isSelectStar()/isSargablecases look cumbersome, and there is something very similar invisitExpression(FieldKeyExpression)already. Maybe you can extract some shared helper and use it in the two places to make it nicer.