diff options
Diffstat (limited to 'src/mongo/db/pipeline/abt/utils.cpp')
-rw-r--r-- | src/mongo/db/pipeline/abt/utils.cpp | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/src/mongo/db/pipeline/abt/utils.cpp b/src/mongo/db/pipeline/abt/utils.cpp index c4d6093cc1b..9911e090305 100644 --- a/src/mongo/db/pipeline/abt/utils.cpp +++ b/src/mongo/db/pipeline/abt/utils.cpp @@ -30,7 +30,7 @@ #include "mongo/db/pipeline/abt/utils.h" #include "mongo/db/exec/sbe/values/bson.h" - +#include "mongo/db/query/optimizer/utils/utils.h" namespace mongo::optimizer { @@ -81,6 +81,39 @@ ABT translateFieldPath(const FieldPath& fieldPath, return result; } +ABT translateFieldRef(const FieldRef& fieldRef, ABT initial) { + ABT result = std::move(initial); + + const size_t fieldPathLength = fieldRef.numParts(); + + // Handle empty field paths separately. + if (fieldPathLength == 0) { + return make<PathGet>("", std::move(result)); + } + + for (size_t i = fieldPathLength; i-- > 0;) { + // A single empty field path will parse to a FieldRef with 0 parts but should + // logically be considered a single part with an empty string. + if (i != fieldPathLength - 1) { + // For field paths with empty elements such as 'x.', we should traverse the + // array 'x' but not reach into any sub-objects. So a predicate such as {'x.': + // {$eq: 5}} should match {x: [5]} and {x: {"": 5}} but not {x: [{"": 5}]}. + const bool trailingEmptyPath = + (fieldPathLength >= 2u && i == fieldPathLength - 2u) && (fieldRef[i + 1] == ""_sd); + if (trailingEmptyPath) { + auto arrCase = make<PathArr>(); + maybeComposePath(arrCase, result.cast<PathGet>()->getPath()); + maybeComposePath<PathComposeA>(result, arrCase); + } else { + result = make<PathTraverse>(std::move(result), PathTraverse::kSingleLevel); + } + } + result = make<PathGet>(fieldRef[i].toString(), std::move(result)); + } + + return result; +} + std::pair<boost::optional<ABT>, bool> getMinMaxBoundForType(const bool isMin, const sbe::value::TypeTags& tag) { switch (tag) { |