void run() { ASSERT(fixDocumentForInsert(_opCtx.getServiceContext(), BSON("_id" << 5)).isOK()); ASSERT( fixDocumentForInsert(_opCtx.getServiceContext(), BSON("_id" << BSON("x" << 5))).isOK()); ASSERT(!fixDocumentForInsert(_opCtx.getServiceContext(), BSON("_id" << BSON("$x" << 5))) .isOK()); ASSERT(!fixDocumentForInsert(_opCtx.getServiceContext(), BSON("_id" << BSON("$oid" << 5))) .isOK()); }
void run() { BSONObj o; { BSONObjBuilder b; b.appendTimestamp( "a" ); b.appendTimestamp( "b" ); b.append( "_id", 1 ); o = b.obj(); } BSONObj fixed = fixDocumentForInsert( o ).getValue(); ASSERT_EQUALS( 3, fixed.nFields() ); ASSERT( fixed.firstElement().fieldNameStringData() == "_id" ); ASSERT( fixed.firstElement().number() == 1 ); BSONElement a = fixed["a"]; ASSERT( o["a"].type() == Timestamp ); ASSERT( o["a"].timestampValue() == 0 ); ASSERT( a.type() == Timestamp ); ASSERT( a.timestampValue() > 0 ); BSONElement b = fixed["b"]; ASSERT( o["b"].type() == Timestamp ); ASSERT( o["b"].timestampValue() == 0 ); ASSERT( b.type() == Timestamp ); ASSERT( b.timestampValue() > 0 ); }
// Does preprocessing of inserts, special casing for indexes // TODO: Simplify this when indexes aren't here anymore static StatusWith<BSONObj> normalizeInsert( const BatchItemRef& insertItem ) { if ( insertItem.getRequest()->isInsertIndexRequest() ) { StatusWith<BSONObj> normalInsert = fixDocumentForInsert( insertItem.getDocument() ); if ( normalInsert.isOK() && insertItem.getDocument()["ns"].type() != String ) { return StatusWith<BSONObj>( ErrorCodes::BadValue, "tried to create an index " "without specifying namespace" ); } else { return normalInsert; } } else { return fixDocumentForInsert( insertItem.getDocument() ); } }
// Goes over the request and preprocesses normalized versions of all the inserts in the request static void normalizeInserts( const BatchedCommandRequest& request, vector<StatusWith<BSONObj> >* normalInserts ) { for ( size_t i = 0; i < request.sizeWriteOps(); ++i ) { BSONObj insertDoc = request.getInsertRequest()->getDocumentsAt( i ); StatusWith<BSONObj> normalInsert = fixDocumentForInsert( insertDoc ); normalInserts->push_back( normalInsert ); if ( request.getOrdered() && !normalInsert.isOK() ) break; } }
void run() { BSONObj x = BSON( "x" << 1 ); ASSERT( x["_id"].type() == 0 ); Collection* collection = _context.db()->getOrCreateCollection( &_txn, ns() ); StatusWith<DiskLoc> dl = collection->insertDocument( &_txn, x, true ); ASSERT( !dl.isOK() ); StatusWith<BSONObj> fixed = fixDocumentForInsert( x ); ASSERT( fixed.isOK() ); x = fixed.getValue(); ASSERT( x["_id"].type() == jstOID ); dl = collection->insertDocument( &_txn, x, true ); ASSERT( dl.isOK() ); }
void run() { WriteUnitOfWork wunit(&_txn); BSONObj x = BSON( "x" << 1 ); ASSERT( x["_id"].type() == 0 ); Collection* collection = _context.db()->getOrCreateCollection( &_txn, ns() ); StatusWith<RecordId> dl = collection->insertDocument( &_txn, x, true ); ASSERT( !dl.isOK() ); StatusWith<BSONObj> fixed = fixDocumentForInsert( x ); ASSERT( fixed.isOK() ); x = fixed.getValue(); ASSERT( x["_id"].type() == jstOID ); dl = collection->insertDocument( &_txn, x, true ); ASSERT( dl.isOK() ); wunit.commit(); }
void run() { WriteUnitOfWork wunit(&_opCtx); BSONObj x = BSON("x" << 1); ASSERT(x["_id"].type() == 0); Collection* collection = _context.db()->getOrCreateCollection(&_opCtx, NamespaceString(ns())); OpDebug* const nullOpDebug = nullptr; ASSERT(!collection->insertDocument(&_opCtx, InsertStatement(x), nullOpDebug, true).isOK()); StatusWith<BSONObj> fixed = fixDocumentForInsert(_opCtx.getServiceContext(), x); ASSERT(fixed.isOK()); x = fixed.getValue(); ASSERT(x["_id"].type() == jstOID); ASSERT(collection->insertDocument(&_opCtx, InsertStatement(x), nullOpDebug, true).isOK()); wunit.commit(); }
void run() { BSONObjBuilder b; b.appendTimestamp("a"); b.append("_id", 1); BSONObj o = b.done(); BSONObj fixed = fixDocumentForInsert(_opCtx.getServiceContext(), o).getValue(); ASSERT_EQUALS(2, fixed.nFields()); ASSERT(fixed.firstElement().fieldNameStringData() == "_id"); ASSERT(fixed.firstElement().number() == 1); BSONElement a = fixed["a"]; ASSERT(o["a"].type() == bsonTimestamp); ASSERT(o["a"].timestampValue() == 0); ASSERT(a.type() == bsonTimestamp); ASSERT(a.timestampValue() > 0); }
// Goes over the request and preprocesses normalized versions of all the inserts in the request static void normalizeInserts( const BatchedCommandRequest& request, vector<StatusWith<BSONObj> >* normalizedInserts, vector<PregeneratedKeys>* pregen ) { normalizedInserts->reserve(request.sizeWriteOps()); for ( size_t i = 0; i < request.sizeWriteOps(); ++i ) { BSONObj insertDoc = request.getInsertRequest()->getDocumentsAt( i ); StatusWith<BSONObj> normalInsert = fixDocumentForInsert( insertDoc ); normalizedInserts->push_back( normalInsert ); if ( request.getOrdered() && !normalInsert.isOK() ) break; if ( !normalInsert.getValue().isEmpty() ) insertDoc = normalInsert.getValue(); pregen->push_back( PregeneratedKeys() ); GeneratorHolder::getInstance()->prepare( request.getTargetingNS(), insertDoc, &pregen->back() ); } }
void run() { ASSERT( fixDocumentForInsert( BSON( "_id" << 5 ) ).isOK() ); ASSERT( fixDocumentForInsert( BSON( "_id" << BSON( "x" << 5 ) ) ).isOK() ); ASSERT( !fixDocumentForInsert( BSON( "_id" << BSON( "$x" << 5 ) ) ).isOK() ); ASSERT( !fixDocumentForInsert( BSON( "_id" << BSON( "$oid" << 5 ) ) ).isOK() ); }
bool WriteCmd::run(const string& dbName, BSONObj& cmdObj, int options, string& errMsg, BSONObjBuilder& result, bool fromRepl) { // Can't be run on secondaries (logTheOp() == false, slaveOk() == false). dassert( !fromRepl ); BatchedCommandRequest request( _writeType ); BatchedCommandResponse response; if ( !request.parseBSON( cmdObj, &errMsg ) || !request.isValid( &errMsg ) ) { // Batch parse failure response.setOk( false ); response.setN( 0 ); response.setErrCode( ErrorCodes::FailedToParse ); response.setErrMessage( errMsg ); dassert( response.isValid( &errMsg ) ); result.appendElements( response.toBSON() ); // TODO // There's a pending issue about how to report response here. If we use // the command infra-structure, we should reuse the 'errmsg' field. But // we have already filed that message inside the BatchCommandResponse. // return response.getOk(); return true; } // Note that this is a runCommmand, and therefore, the database and the collection name // are in different parts of the grammar for the command. But it's more convenient to // work with a NamespaceString. We built it here and replace it in the parsed command. // Internally, everything work with the namespace string as opposed to just the // collection name. NamespaceString nss(dbName, request.getNS()); request.setNS(nss.ns()); Status status = userAllowedWriteNS( nss ); if ( !status.isOK() ) return appendCommandStatus( result, status ); if ( cc().curop() ) cc().curop()->setNS( nss.ns() ); if ( request.getBatchType() == BatchedCommandRequest::BatchType_Insert ) { // check all docs BatchedInsertRequest* insertRequest = request.getInsertRequest(); vector<BSONObj>& docsToInsert = insertRequest->getDocuments(); for ( size_t i = 0; i < docsToInsert.size(); i++ ) { StatusWith<BSONObj> fixed = fixDocumentForInsert( docsToInsert[i] ); if ( !fixed.isOK() ) { // we don't return early since each doc can be handled independantly continue; } if ( fixed.getValue().isEmpty() ) { continue; } docsToInsert[i] = fixed.getValue(); } } BSONObj defaultWriteConcern; // This is really bad - it's only safe because we leak the defaults by overriding them with // new defaults and because we never reset to an empty default. // TODO: fix this for sane behavior where we query repl set object if ( getLastErrorDefault ) defaultWriteConcern = *getLastErrorDefault; if ( defaultWriteConcern.isEmpty() ) { BSONObjBuilder b; b.append( "w", 1 ); defaultWriteConcern = b.obj(); } WriteBatchExecutor writeBatchExecutor(defaultWriteConcern, &cc(), &globalOpCounters, lastError.get()); writeBatchExecutor.executeBatch( request, &response ); result.appendElements( response.toBSON() ); // TODO // There's a pending issue about how to report response here. If we use // the command infra-structure, we should reuse the 'errmsg' field. But // we have already filed that message inside the BatchCommandResponse. // return response.getOk(); return true; }