* Core traversal logic into a bson document. This walks the documentIterator * to look for a given traversePath and applies the extension functions from * ExtensionFuncs based on the traverse behavior. * This is a purely internal function used by TraverseBson to handle parsing. * * This function returns true if the path being searched for (or descendant paths) * are not found. */
| 935 | * are not found. |
| 936 | */ |
| 937 | static bool |
| 938 | TraverseBsonCore(bson_iter_t *documentIterator, const StringView *traversePath, |
| 939 | void *state, |
| 940 | const TraverseBsonExecutionFuncs *executionFunctions, |
| 941 | bool inArrayContext) |
| 942 | { |
| 943 | check_stack_depth(); |
| 944 | CHECK_FOR_INTERRUPTS(); |
| 945 | const StringView dotKeyStr = StringViewFindPrefix(traversePath, '.'); |
| 946 | pgbsonelement documentFieldElement; |
| 947 | |
| 948 | /* |
| 949 | * When the traversal path is a single field (no dots), |
| 950 | * We first call the Visit function against the top level field, |
| 951 | * and if it's an array the VisitArrayField as well. |
| 952 | * |
| 953 | * When the traversePath has composite fields (e.g. "a.b.c"), we recurse into objects/arrays |
| 954 | * in the document until we have a single field. |
| 955 | */ |
| 956 | if (dotKeyStr.string == NULL) |
| 957 | { |
| 958 | /* no dot key - find the field in the current bson. */ |
| 959 | if (!bson_iter_find_string_view(documentIterator, traversePath)) |
| 960 | { |
| 961 | if (executionFunctions->SetTraverseResult != NULL) |
| 962 | { |
| 963 | executionFunctions->SetTraverseResult(state, |
| 964 | TraverseBsonResult_PathNotFound); |
| 965 | } |
| 966 | |
| 967 | return true; |
| 968 | } |
| 969 | |
| 970 | BsonIterToPgbsonElement(documentIterator, &documentFieldElement); |
| 971 | bool shouldContinue = executionFunctions->VisitTopLevelField( |
| 972 | &documentFieldElement, traversePath, state); |
| 973 | if (!shouldContinue) |
| 974 | { |
| 975 | return false; |
| 976 | } |
| 977 | |
| 978 | /* if the last field is an array, compare the value against the elements in the array as well. |
| 979 | * Note that protocol does not traverse arrays of arrays, so if the caller is an array, skip this |
| 980 | * recursion. |
| 981 | */ |
| 982 | if (BSON_ITER_HOLDS_ARRAY(documentIterator) && |
| 983 | !inArrayContext && |
| 984 | executionFunctions->VisitArrayField != NULL) |
| 985 | { |
| 986 | bson_iter_t nestedIterator; |
| 987 | bson_iter_recurse(documentIterator, &nestedIterator); |
| 988 | int arrayIndex = 0; |
| 989 | while (bson_iter_next(&nestedIterator)) |
| 990 | { |
| 991 | /* Comparisons only work on the same sort order type. */ |
| 992 | BsonIterToPgbsonElement(&nestedIterator, &documentFieldElement); |
| 993 | shouldContinue = executionFunctions->VisitArrayField( |
| 994 | &documentFieldElement, traversePath, arrayIndex, state); |
no test coverage detected