'use strict'; const GetMore = require('../connection/commands').GetMore; const retrieveBSON = require('../connection/utils').retrieveBSON; const MongoError = require('../error').MongoError; const MongoNetworkError = require('../error').MongoNetworkError; const BSON = retrieveBSON(); const Long = BSON.Long; const collectionNamespace = require('./shared').collectionNamespace; const maxWireVersion = require('../utils').maxWireVersion; const applyCommonQueryOptions = require('./shared').applyCommonQueryOptions; const command = require('./command'); function getMore(server, ns, cursorState, batchSize, options, callback) { options = options || {}; const wireVersion = maxWireVersion(server); function queryCallback(err, result) { if (err) return callback(err); const response = result.message; // If we have a timed out query or a cursor that was killed if (response.cursorNotFound) { return callback(new MongoNetworkError('cursor killed or timed out'), null); } if (wireVersion < 4) { const cursorId = typeof response.cursorId === 'number' ? Long.fromNumber(response.cursorId) : response.cursorId; cursorState.documents = response.documents; cursorState.cursorId = cursorId; callback(null, null, response.connection); return; } // We have an error detected if (response.documents[0].ok === 0) { return callback(new MongoError(response.documents[0])); } // Ensure we have a Long valid cursor id const cursorId = typeof response.documents[0].cursor.id === 'number' ? Long.fromNumber(response.documents[0].cursor.id) : response.documents[0].cursor.id; cursorState.documents = response.documents[0].cursor.nextBatch; cursorState.cursorId = cursorId; callback(null, response.documents[0], response.connection); } if (wireVersion < 4) { const bson = server.s.bson; const getMoreOp = new GetMore(bson, ns, cursorState.cursorId, { numberToReturn: batchSize }); const queryOptions = applyCommonQueryOptions({}, cursorState); server.s.pool.write(getMoreOp, queryOptions, queryCallback); return; } const getMoreCmd = { getMore: cursorState.cursorId, collection: collectionNamespace(ns), batchSize: Math.abs(batchSize) }; if (cursorState.cmd.tailable && typeof cursorState.cmd.maxAwaitTimeMS === 'number') { getMoreCmd.maxTimeMS = cursorState.cmd.maxAwaitTimeMS; } const commandOptions = Object.assign( { returnFieldSelector: null, documentsReturnedIn: 'nextBatch' }, options ); command(server, ns, getMoreCmd, commandOptions, queryCallback); } module.exports = getMore;