DocumentSource.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. var DocumentSource = module.exports = (function(){
  2. // CONSTRUCTOR
  3. /**
  4. * A base class for all document sources
  5. * @param {ExpressionContext}
  6. **/
  7. var klass = module.exports = DocumentSource = function DocumentSource(/*pCtx*/){
  8. if(arguments.length !== 0) throw new Error("zero args expected");
  9. /*
  10. Most DocumentSources have an underlying source they get their data
  11. from. This is a convenience for them.
  12. The default implementation of setSource() sets this; if you don't
  13. need a source, override that to verify(). The default is to
  14. verify() if this has already been set.
  15. */
  16. this.pSource = null;
  17. /*
  18. The zero-based user-specified pipeline step. Used for diagnostics.
  19. Will be set to -1 for artificial pipeline steps that were not part
  20. of the original user specification.
  21. */
  22. this.step = -1;
  23. //we dont need this because we are not sharding
  24. //intrusive_ptr<ExpressionContext> pExpCtx;
  25. //this.pExpCtx = pCtx;
  26. /*
  27. for explain: # of rows returned by this source
  28. This is *not* unsigned so it can be passed to JSONObjBuilder.append().
  29. */
  30. this.nRowsOut = 0;
  31. }, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  32. /*
  33. class DocumentSource :
  34. public IntrusiveCounterUnsigned,
  35. public StringWriter {
  36. public:
  37. virtual ~DocumentSource();
  38. // virtuals from StringWriter
  39. virtual void writeString(stringstream &ss) const;
  40. */
  41. /**
  42. * Set the step for a user-specified pipeline step.
  43. *
  44. * @method setPipelineStep
  45. * @param {Number} step number 0 to n.
  46. **/
  47. proto.setPipelineStep = function setPipelineStep(step) {
  48. this.step = step;
  49. };
  50. /**
  51. * Get the user-specified pipeline step.
  52. *
  53. * @method getPipelineStep
  54. * @returns {Number} step
  55. **/
  56. proto.getPipelineStep = function getPipelineStep() {
  57. return this.step;
  58. };
  59. /**
  60. * Is the source at EOF?
  61. *
  62. * @method eof
  63. **/
  64. proto.eof = function eof() {
  65. throw new Error("not implemented");
  66. };
  67. /**
  68. * Advance the state of the DocumentSource so that it will return the next Document.
  69. * The default implementation returns false, after checking for interrupts.
  70. * Derived classes can call the default implementation in their own implementations in order to check for interrupts.
  71. *
  72. * @method advance
  73. * @returns {Boolean} whether there is another document to fetch, i.e., whether or not getCurrent() will succeed. This default implementation always returns false.
  74. **/
  75. proto.advance = function advance() {
  76. //pExpCtx->checkForInterrupt(); // might not return
  77. return false;
  78. };
  79. /**
  80. * some implementations do the equivalent of verify(!eof()) so check eof() first
  81. *
  82. * @method getCurrent
  83. * @returns {Document} the current Document without advancing
  84. **/
  85. proto.getCurrent = function getCurrent() {
  86. throw new Error("not implemented");
  87. };
  88. /**
  89. * Inform the source that it is no longer needed and may release its resources. After
  90. * dispose() is called the source must still be able to handle iteration requests, but may
  91. * become eof().
  92. * NOTE: For proper mutex yielding, dispose() must be called on any DocumentSource that will
  93. * not be advanced until eof(), see SERVER-6123.
  94. *
  95. * @method dispose
  96. **/
  97. proto.dispose = function dispose() {
  98. if ( this.pSource ) {
  99. // This is required for the DocumentSourceCursor to release its read lock, see
  100. // SERVER-6123.
  101. this.pSource.dispose();
  102. }
  103. };
  104. /**
  105. * Get the source's name.
  106. *
  107. * @method getSourceName
  108. * @returns {String} the string name of the source as a constant string; this is static, and there's no need to worry about adopting it
  109. **/
  110. proto.getSourceName = function getSourceName() {
  111. return "[UNKNOWN]";
  112. };
  113. /**
  114. * Set the underlying source this source should use to get Documents
  115. * from.
  116. * It is an error to set the source more than once. This is to
  117. * prevent changing sources once the original source has been started;
  118. * this could break the state maintained by the DocumentSource.
  119. * This pointer is not reference counted because that has led to
  120. * some circular references. As a result, this doesn't keep
  121. * sources alive, and is only intended to be used temporarily for
  122. * the lifetime of a Pipeline::run().
  123. *
  124. * @method setSource
  125. * @param {DocumentSource} pSource the underlying source to use
  126. **/
  127. proto.setSource = function setSource(pTheSource) {
  128. if(this.pSource){
  129. throw new Error("It is an error to set the source more than once");
  130. }
  131. this.pSource = pTheSource;
  132. };
  133. /**
  134. * Attempt to coalesce this DocumentSource with its successor in the
  135. * document processing pipeline. If successful, the successor
  136. * DocumentSource should be removed from the pipeline and discarded.
  137. * If successful, this operation can be applied repeatedly, in an
  138. * attempt to coalesce several sources together.
  139. * The default implementation is to do nothing, and return false.
  140. *
  141. * @method coalesce
  142. * @param {DocumentSource} pNextSource the next source in the document processing chain.
  143. * @returns {Boolean} whether or not the attempt to coalesce was successful or not; if the attempt was not successful, nothing has been changed
  144. **/
  145. proto.coalesce = function coalesce(pNextSource) {
  146. return false;
  147. };
  148. /**
  149. * Optimize the pipeline operation, if possible. This is a local
  150. * optimization that only looks within this DocumentSource. For best
  151. * results, first coalesce compatible sources using coalesce().
  152. * This is intended for any operations that include expressions, and
  153. * provides a hook for those to optimize those operations.
  154. * The default implementation is to do nothing.
  155. *
  156. * @method optimize
  157. **/
  158. proto.optimize = function optimize(pNextSource) {
  159. };
  160. klass.GetDepsReturn = {
  161. NOT_SUPPORTED:"NOT_SUPPORTED", // This means the set should be ignored
  162. EXHAUSTIVE:"EXHAUSTIVE", // This means that everything needed should be in the set
  163. SEE_NEXT:"SEE_NEXT", // Add the next Source's deps to the set
  164. };
  165. /**
  166. * Get the fields this operation needs to do its job.
  167. * Deps should be in "a.b.c" notation
  168. *
  169. * @method getDependencies
  170. * @param {Object} deps set (unique array) of strings
  171. * @returns DocumentSource.GetDepsReturn
  172. **/
  173. proto.getDependencies = function getDependencies(deps) {
  174. return klass.GetDepsReturn.NOT_SUPPORTED;
  175. };
  176. /**
  177. * This takes dependencies from getDependencies and
  178. * returns a projection that includes all of them
  179. *
  180. * @method depsToProjection
  181. * @param {Object} deps set (unique array) of strings
  182. * @returns {Object} JSONObj
  183. **/
  184. klass.depsToProjection = function depsToProjection(deps) {
  185. var bb = {};
  186. if (deps._id === undefined)
  187. bb._id = 0;
  188. var last = "";
  189. Object.keys(deps).forEach(function(it){
  190. if (last !== "" && it.slice(0, last.length) === last){
  191. // we are including a parent of *it so we don't need to
  192. // include this field explicitly. In fact, due to
  193. // SERVER-6527 if we included this field, the parent
  194. // wouldn't be fully included.
  195. return;
  196. }
  197. last = it + ".";
  198. bb[it] = 1;
  199. });
  200. return bb;
  201. };
  202. /**
  203. * Add the DocumentSource to the array builder.
  204. * The default implementation calls sourceToJson() in order to
  205. * convert the inner part of the object which will be added to the
  206. * array being built here.
  207. *
  208. * @method addToJsonArray
  209. * @param {Array} pBuilder JSONArrayBuilder: the array builder to add the operation to.
  210. * @param {Boolean} explain create explain output
  211. * @returns {Object}
  212. **/
  213. proto.addToJsonArray = function addToJsonArray(pBuilder, explain) {
  214. pBuilder.push(this.sourceToJson({}, explain));
  215. };
  216. /**
  217. * Create an object that represents the document source. The object
  218. * will have a single field whose name is the source's name. This
  219. * will be used by the default implementation of addToJsonArray()
  220. * to add this object to a pipeline being represented in JSON.
  221. *
  222. * @method sourceToJson
  223. * @param {Object} pBuilder JSONObjBuilder: a blank object builder to write to
  224. * @param {Boolean} explain create explain output
  225. **/
  226. proto.sourceToJson = function sourceToJson(pBuilder, explain) {
  227. throw new Error("not implemented");
  228. };
  229. /**
  230. * Reset the document source so that it is ready for a new stream of data.
  231. * Note that this is a deviation from the mongo implementation.
  232. *
  233. * @method reset
  234. **/
  235. proto.reset = function reset(){
  236. throw new Error("not implemented");
  237. };
  238. return klass;
  239. })();