SERVER-125693 Refactor new base field logic (#53196)
GitOrigin-RevId: 749e35a6ee4589881cd881d573e537656c0ee88d
This commit is contained in:
parent
1d4ffa7619
commit
3c5dfe63ec
@ -759,18 +759,8 @@ private:
|
||||
// updated embedded scope.
|
||||
auto embeddedScope = _scopes.getNextId();
|
||||
newBaseField = _fields.append(Field{scope, embeddedScope});
|
||||
auto parentEmbeddedScope =
|
||||
existingBaseField ? _fields[existingBaseField].embeddedScope : ScopeId::none();
|
||||
// Where unknown subfields originate:
|
||||
// - no previous field -> base collection.
|
||||
// - previous field's scope is exhaustive -> inherit it.
|
||||
// - previous field is a leaf in a non-exhaustive scope -> this new scope.
|
||||
auto exhaustiveEmbeddedScope = existingBaseField
|
||||
? _scopes[_fields[existingBaseField].declaringScope].exhaustiveScope
|
||||
: ScopeId::none();
|
||||
if (existingBaseField && !parentEmbeddedScope && !exhaustiveEmbeddedScope) {
|
||||
exhaustiveEmbeddedScope = embeddedScope;
|
||||
}
|
||||
auto [exhaustiveEmbeddedScope, parentEmbeddedScope] =
|
||||
resolveNewBaseFieldScopes(existingBaseField, embeddedScope);
|
||||
if (parentEmbeddedScope) {
|
||||
// The new field depends on the previous field, since it inherits paths.
|
||||
_fields[newBaseField].dependencies.insert(existingBaseField);
|
||||
@ -792,6 +782,36 @@ private:
|
||||
return newBaseField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ScopeIds for a new base field.
|
||||
* 'existingBaseField' is the result of looking up the base field.
|
||||
* 'embeddedScope' is the ScopeId for the new scope that will be created for the base field.
|
||||
*/
|
||||
std::pair<ScopeId, ScopeId> resolveNewBaseFieldScopes(FieldId existingBaseField,
|
||||
ScopeId embeddedScope) const {
|
||||
auto parentEmbeddedScope =
|
||||
existingBaseField ? _fields[existingBaseField].embeddedScope : ScopeId::none();
|
||||
// Where unknown subfields originate:
|
||||
auto exhaustiveEmbeddedScope = [&]() {
|
||||
if (!existingBaseField) {
|
||||
// No previous field -> base collection.
|
||||
return ScopeId::none();
|
||||
}
|
||||
if (auto previousExhaustiveScope =
|
||||
_scopes[_fields[existingBaseField].declaringScope].exhaustiveScope) {
|
||||
// Previous field's scope is exhaustive -> inherit it.
|
||||
return previousExhaustiveScope;
|
||||
}
|
||||
if (!parentEmbeddedScope) {
|
||||
// Previous field is a leaf in a non-exhaustive scope -> this new scope
|
||||
return embeddedScope;
|
||||
}
|
||||
// TODO(SERVER-126001): We should not return none here.
|
||||
return ScopeId::none();
|
||||
}();
|
||||
return {exhaustiveEmbeddedScope, parentEmbeddedScope};
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the field from the parent scope into the given scope.
|
||||
* This has the semantics of an inclusion projection.
|
||||
|
||||
@ -1277,6 +1277,18 @@ TEST_F(PipelineDependencyGraphTest, SetFieldThenIncludeDottedPath) {
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(PipelineDependencyGraphTest, DottedPathAfterBaseField) {
|
||||
setPipeline(
|
||||
"[{$set: { a: 1 }},"
|
||||
"{$set: { 'a.a': 1 }},"
|
||||
"{$set: { 'a.b.a': 1 }}]");
|
||||
|
||||
runTest([&] {
|
||||
// TODO(SERVER-126001): a.x was modified by the first stage
|
||||
ASSERT_EQUALS(graph->getDeclaringStage(nullptr, "a.x"), nullptr) << graph->toDebugString();
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(PipelineDependencyGraphTest, ComplexPathsMultiple) {
|
||||
setPipeline(
|
||||
"[{$set: { a: 1, b: 1, 'c.c': 1 }},"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user