MCPcopy Create free account
hub / github.com/FoundationDB/fdb-document-layer / parseProjection

Function parseProjection

src/ExtUtil.actor.cpp:834–921  ·  view source on GitHub ↗

Parse a Projection tree from a BSON projection specification

Source from the content-addressed store, hash-verified

832
833// Parse a Projection tree from a BSON projection specification
834Reference<Projection> parseProjection(bson::BSONObj const& fieldSelector) {
835 std::set<std::string> parsedFields;
836 bool includeID = true;
837 bool hasIncludeValue = false;
838
839 Reference<Projection> root(new Projection());
840
841 for (auto itr = fieldSelector.begin(); itr.more(); ++itr) {
842 bson::BSONElement el = *itr;
843 std::string fieldName = el.fieldName();
844 if (fieldName.length() >= 2 && fieldName.compare(fieldName.length() - 2, 2, ".$") == 0) {
845 // TODO: $ operator
846 throw invalid_projection();
847 } else if (el.type() == bson::Object) {
848 // TODO: $slice operator
849 // TODO: $elemMatch operator
850 // TODO: $meta operator
851 throw invalid_projection();
852 } else {
853 bool elIncluded = el.trueValue();
854 if (fieldName == DocLayerConstants::ID_FIELD) {
855 // Specifying _id:1 makes the projection an inclusive projection
856 if (elIncluded) {
857 if (hasIncludeValue && root->included) {
858 throw invalid_projection();
859 }
860
861 root->included = false; // Our specification is inclusive, so unspecified fields should be excluded
862 hasIncludeValue = true;
863 }
864
865 includeID = elIncluded;
866 } else {
867 if (!hasIncludeValue) {
868 root->included =
869 !elIncluded; // If el was inclusive, then we should exclude unspecified fields (and vice versa)
870 hasIncludeValue = true;
871 }
872
873 // inclusive and exclusive modes cannot be mixed
874 else if (root->included == elIncluded) {
875 throw invalid_projection();
876 }
877
878 // The whole _id field is either included or excluded as a unit regardless of whether its sub-fields are
879 // included in the projection
880 if (fieldName.size() >= 4 && fieldName.compare(0, 4, "_id.") == 0) {
881 continue;
882 }
883
884 // Split the field into its consituent parts and insert the parts into the Projection tree
885 if (parsedFields.insert(fieldName).second) {
886 size_t pos = -1;
887 size_t prev;
888 Reference<Projection>* current = &root;
889 do {
890 prev = pos + 1;
891 pos = fieldName.find('.', prev);

Calls 5

beginMethod · 0.80
findMethod · 0.80
compareMethod · 0.45
sizeMethod · 0.45
insertMethod · 0.45

Tested by

no test coverage detected