Status storageValidChildren(const mb::ConstElement& elem, const bool deep) { if (!elem.hasChildren()) return Status::OK(); mb::ConstElement curr = elem.leftChild(); while (curr.ok()) { Status s = storageValid(curr, deep); if (!s.isOK()) return s; curr = curr.rightSibling(); } return Status::OK(); }
/** * Checks that all parents, of the element passed in, are valid for storage * * Note: The elem argument must be in a valid state when using this function */ Status storageValidParents(const mb::ConstElement& elem) { const mb::ConstElement& root = elem.getDocument().root(); if (elem != root) { const mb::ConstElement& parent = elem.parent(); if (parent.ok() && parent != root) { Status s = storageValid(parent, false); if (s.isOK()) { s = storageValidParents(parent); } return s; } } return Status::OK(); }
Status storageValid(const mb::ConstElement& elem, const bool deep) { if (!elem.ok()) return Status(ErrorCodes::BadValue, "Invalid elements cannot be stored."); // Field names of elements inside arrays are not meaningful in mutable bson, // so we do not want to validate them. // // TODO: Revisit how mutable handles array field names. We going to need to make // this better if we ever want to support ordered updates that can alter the same // element repeatedly; see SERVER-12848. const mb::ConstElement& parent = elem.parent(); const bool childOfArray = parent.ok() ? (parent.getType() == mongo::Array) : false; if (!childOfArray) { StringData fieldName = elem.getFieldName(); // Cannot start with "$", unless dbref if (fieldName[0] == '$') { Status status = validateDollarPrefixElement(elem, deep); if (!status.isOK()) return status; } else if (fieldName.find(".") != string::npos) { // Field name cannot have a "." in it. return Status(ErrorCodes::DottedFieldName, str::stream() << "The dotted field '" << elem.getFieldName() << "' in '" << mb::getFullName(elem) << "' is not valid for storage."); } } if (deep) { // Check children if there are any. Status s = storageValidChildren(elem, deep); if (!s.isOK()) return s; } return Status::OK(); }