summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/abt/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/abt/utils.cpp')
-rw-r--r--src/mongo/db/pipeline/abt/utils.cpp35
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) {