Browse Source

refs #5132: create outdocsource pass-through and simple test cases

Patrick Rigney 11 years ago
parent
commit
3eb715133c

+ 30 - 90
lib/pipeline/documentSources/OutDocumentSource.js

@@ -1,117 +1,57 @@
 "use strict";
 
+var DocumentSource = require('./DocumentSource');
+
 /**
- * A document source skipper
  * @class OutDocumentSource
  * @namespace mungedb-aggregate.pipeline.documentSources
  * @module mungedb-aggregate
  * @constructor
  * @param [ctx] {ExpressionContext}
  **/
-var OutDocumentSource = module.exports = function OutDocumentSource(ctx){
+var OutDocumentSource = module.exports = function OutDocumentSource(outputNs, ctx){
+	if (arguments.length > 2) throw new Error("up to two arg expected");
+	base.call(this, ctx);
+	// defaults
+	this._done = false;
+	this._outputNs = outputNs;
+	this._collectionName = "";
 }, klass = OutDocumentSource, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 klass.outName = "$out";
-proto.getSourceName = function getSourceName(){
-	return klass.outName;
-};
-
-/**
- * Coalesce skips together
- * @param {Object} nextSource the next source
- * @return {bool} return whether we can coalese together
- **/
-proto.coalesce = function coalesce(nextSource) {
-	var nextSkip =	nextSource.constructor === OutDocumentSource?nextSource:null;
 
-	// if it's not another $skip, we can't coalesce
-	if (!nextSkip) return false;
-
-	// we need to skip over the sum of the two consecutive $skips
-	this.skip += nextSkip.skip;
-	return true;
+proto.getSourceName = function() {
+	return klass.outName;
 };
 
-proto.skipper = function skipper() {
-	if (this.count === 0) {
-		while (!this.source.eof() && this.count++ < this.skip) {
-			this.source.advance();
-		}
-	}
-
-	if (this.source.eof()) {
-		this.current = null;
-		return;
-	}
+proto.getNext = function(callback) {
+	if (!callback) throw new Error(this.getSourceName() + ' #getNext() requires callback');
 
-	this.current = this.source.getCurrent();
+	return this.source.getNext(callback);
 };
 
-
-/**
- * Is the source at EOF?
- * @method	eof
- **/
-proto.eof = function eof() {
-	this.skipper();
-	return this.source.eof();
+proto.serialize = function(explain) {
+	var doc = {},
+		srcNm = this.getSourceName();
+	doc[srcNm] = this._collectionName;
+	return doc;
 };
 
-/**
- * some implementations do the equivalent of verify(!eof()) so check eof() first
- * @method	getCurrent
- * @returns	{Document}	the current Document without advancing
- **/
-proto.getCurrent = function getCurrent() {
-	this.skipper();
-	return this.source.getCurrent();
+proto.getOutputNs = function() {
+	return this._outputNs;
 };
 
-/**
- * Advance the state of the DocumentSource so that it will return the next Document.
- * The default implementation returns false, after checking for interrupts.
- * Derived classes can call the default implementation in their own implementations in order to check for interrupts.
- *
- * @method	advance
- * @returns	{Boolean}	whether there is another document to fetch, i.e., whether or not getCurrent() will succeed.  This default implementation always returns false.
- **/
-proto.advance = function advance() {
-	base.prototype.advance.call(this); // check for interrupts
-	if (this.eof()) {
-		this.current = null;
-		return false;
-	}
+klass.createFromJson = function(jsonElement, ctx) {
+	if (typeof jsonElement !== 'string')
+		throw new Error('code 16990; $out only supports a string argument, not ' + typeof jsonElement);
 
-	this.current = this.source.getCurrent();
-	return this.source.advance();
-};
+	var out = new OutDocumentSource(null, ctx); // TODO: outputNs
+	out._collectionName = jsonElement;
 
-/**
- * Create an object that represents the document source.  The object
- * will have a single field whose name is the source's name.  This
- * will be used by the default implementation of addToJsonArray()
- * to add this object to a pipeline being represented in JSON.
- *
- * @method	sourceToJson
- * @param	{Object} builder	JSONObjBuilder: a blank object builder to write to
- * @param	{Boolean}	explain	create explain output
- **/
-proto.sourceToJson = function sourceToJson(builder, explain) {
-	builder.$skip = this.skip;
+	return out;
 };
 
-/**
- * Creates a new OutDocumentSource with the input number as the skip
- *
- * @param {Number} JsonElement this thing is *called* Json, but it expects a number
- **/
-klass.createFromJson = function createFromJson(jsonElement, ctx) {
-	if (typeof jsonElement !== "number") throw new Error("code 15972; the value to skip must be a number");
-
-	var nextSkip = new OutDocumentSource(ctx);
-
-	nextSkip.skip = jsonElement;
-	if (nextSkip.skip < 0 || isNaN(nextSkip.skip)) throw new Error("code 15956; the number to skip cannot be negative");
-
-	return nextSkip;
+proto.getDependencies = function(deps) {
+	deps.needWholeDocument = true;
+	return DocumentSource.GetDepsReturn.EXHAUSTIVE;
 };

+ 74 - 0
test/lib/pipeline/documentSources/OutDocumentSource.js

@@ -0,0 +1,74 @@
+"use strict";
+var assert = require("assert"),
+	DocumentSource = require("../../../../lib/pipeline/documentSources/DocumentSource"),
+	OutDocumentSource = require("../../../../lib/pipeline/documentSources/OutDocumentSource"),
+	CursorDocumentSource = require("../../../../lib/pipeline/documentSources/CursorDocumentSource"),
+	Cursor = require("../../../../lib/Cursor");
+
+var createOut = function(ctx) {
+	var ds = new OutDocumentSource(ctx);
+	return ds;
+};
+
+module.exports = {
+
+	"OutDocumentSource": {
+
+		"constructor()":{
+
+			"should not throw when constructing without args":function() {
+				assert.doesNotThrow(function(){
+					var ods = createOut();
+				});
+			}
+
+		},
+
+		"#getSourceName()":{
+
+			"should return the correct source name; $out": function() {
+				var ods = createOut();
+				assert.strictEqual(ods.getSourceName(), "$out");
+			}
+
+		},
+
+		"#getNext()":{
+
+			"callback is required":function() {
+				var ods = createOut();
+				assert.throws(ods.getNext.bind(ods));
+			}
+		},
+
+		"#createFromJson()":{
+
+			"method creates OutDocumentSource with given title":function() {
+				var title = "CognitiveScientists",
+					ods = OutDocumentSource.createFromJson(title);
+
+				assert.strictEqual(title, ods._collectionName);
+			}
+		},
+
+		"#serialize()":{
+
+			"serialize":function() {
+				var cwc = new CursorDocumentSource.CursorWithContext();
+				var input = [{_id: 0, a: 1}, {_id: 1, a: 2}];
+				cwc._cursor = new Cursor( input );
+				var cds = new CursorDocumentSource(cwc);
+				var title = "CognitiveScientists";
+				var ods = OutDocumentSource.createFromJson(title);
+				ods.setSource(cds);
+				var srcNm = ods.getSourceName();
+				var serialize = {};
+				serialize[srcNm] = title;
+
+				assert.deepEqual(ods.serialize(), serialize);
+			}
+		}
+	}
+};
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).grep(process.env.MOCHA_GREP || '').run(process.exit);