void insertObjects(const char *ns, const vector<BSONObj> &objs, bool keepGoing, uint64_t flags, bool logop ) { if (mongoutils::str::contains(ns, "system.")) { massert(16748, "need transaction to run insertObjects", cc().txnStackSize() > 0); uassert(10095, "attempt to insert in reserved database name 'system'", !mongoutils::str::startsWith(ns, "system.")); massert(16750, "attempted to insert multiple objects into a system namspace at once", objs.size() == 1); if (handle_system_collection_insert(ns, objs[0], logop) != 0) { return; } } NamespaceDetails *details = getAndMaybeCreateNS(ns, logop); NamespaceDetailsTransient *nsdt = &NamespaceDetailsTransient::get(ns); for (size_t i = 0; i < objs.size(); i++) { const BSONObj &obj = objs[i]; try { uassert( 10059 , "object to insert too large", obj.objsize() <= BSONObjMaxUserSize); BSONObjIterator i( obj ); while ( i.more() ) { BSONElement e = i.next(); uassert( 13511 , "document to insert can't have $ fields" , e.fieldName()[0] != '$' ); } uassert( 16440 , "_id cannot be an array", obj["_id"].type() != Array ); BSONObj objModified = obj; BSONElementManipulator::lookForTimestamps(objModified); if (details->isCapped() && logop) { // unfortunate hack we need for capped collections // we do this because the logic for generating the pk // and what subsequent rows to delete are buried in the // namespace details object. There is probably a nicer way // to do this, but this works. details->insertObjectIntoCappedAndLogOps(objModified, flags); if (nsdt != NULL) { nsdt->notifyOfWriteOp(); } } else { insertOneObject(details, nsdt, objModified, flags); // may add _id field if (logop) { OpLogHelpers::logInsert(ns, objModified, &cc().txn()); } } } catch (const UserException &) { if (!keepGoing || i == objs.size() - 1) { throw; } } } }
// Does not check magic system collection inserts. void _insertObjects(const char *ns, const vector<BSONObj> &objs, bool keepGoing, uint64_t flags, bool logop ) { NamespaceDetails *details = getAndMaybeCreateNS(ns, logop); for (size_t i = 0; i < objs.size(); i++) { const BSONObj &obj = objs[i]; try { uassert( 10059 , "object to insert too large", obj.objsize() <= BSONObjMaxUserSize); BSONObjIterator i( obj ); while ( i.more() ) { BSONElement e = i.next(); // check no $ modifiers. note we only check top level. // (scanning deep would be quite expensive) uassert( 13511 , "document to insert can't have $ fields" , e.fieldName()[0] != '$' ); // check no regexp for _id (SERVER-9502) if (str::equals(e.fieldName(), "_id")) { uassert(17033, "can't use a regex for _id", e.type() != RegEx); } } uassert( 16440 , "_id cannot be an array", obj["_id"].type() != Array ); BSONObj objModified = obj; BSONElementManipulator::lookForTimestamps(objModified); if (details->isCapped() && logop) { // unfortunate hack we need for capped collections // we do this because the logic for generating the pk // and what subsequent rows to delete are buried in the // namespace details object. There is probably a nicer way // to do this, but this works. details->insertObjectIntoCappedAndLogOps(objModified, flags); details->notifyOfWriteOp(); } else { insertOneObject(details, objModified, flags); // may add _id field if (logop) { OpLogHelpers::logInsert(ns, objModified); } } } catch (const UserException &) { if (!keepGoing || i == objs.size() - 1) { throw; } } } }