Browse Source

EAGLESIX-3010: Created new WhereMatchExpression, updated package.json for contributors.

David Aebersold 11 years ago
parent
commit
1e5400d01a

+ 192 - 0
lib/pipeline/matcher/WhereMatchExpression.js

@@ -0,0 +1,192 @@
+"use strict";
+
+var WhereMatchExpression = module.exports = function WhereMatchExpression( txn ){
+	this._txn = txn;
+	this._matchType = 'MATCH_WHERE';
+}, klass = WhereMatchExpression, base =  Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+// DEPENDENCIES
+var errors = require("../../Errors.js"),
+	ErrorCodes = errors.ErrorCodes,
+	MatchExpression = require("./MatchExpression.js"),
+	MatchExpressionParser = require("./MatchExpressionParser.js");
+
+proto._txn = undefined;
+proto._func = 0;
+proto._dbName = undefined;
+proto._ns = undefined;
+proto._code = undefined;
+proto._userScope = undefined;
+proto._scope = undefined;
+
+/**
+ *
+ * Initialize the necessary items
+ * @method init
+ * @param dbName
+ * @param theCode
+ * @param scope
+ *
+ */
+proto.init = function init(dbName, theCode, scope) {
+	if ( dbName === undefined ) {
+		return {'code':'BAD_VALUE', 'description':'ns for $where cannot be empty'};
+	}
+	if ( theCode === undefined ) {
+		return {'code':'BAD_VALUE', 'description':'code for $where cannot be empty'};
+	}
+
+	this._dbName = dbName;
+	this._code = theCode;
+
+	// TODO: Not implementing for now.
+
+	this._userScope = scope.getOwned();
+	var userToken = this.getAuthorizationSession().getAuthenticatedUserNamesToken();
+	this._scope = this.globalScriptEngine.getPooledScope(this._txn, this._dbName, "where" + userToken);
+	this._func = this._scope.createFunction( this._code.c_str() );
+	if ( !this._func) {
+		return {'code':'BAD_VALUE', 'description':'$where compile error'};
+	}
+
+	return {'code':'OK'};
+};
+
+
+/**
+ *
+ * Matches the necessary items
+ * @method matches
+ * @param doc
+ * @param details
+ *
+ */
+proto.matches = function matches(doc, details) {
+	var obj = JSON.stringify(doc);
+
+	if ( this._userScope === undefined ){
+		this._scope.init( this._userScope);
+	}
+
+	this._scope.obj = obj;
+	this._scope.fullObject = true;
+
+	var err = this._scope.invoke( this._func, 0, obj, 1000 * 60, false);
+	if ( err == -3) { // INVOKE_ERROR
+		var ss = "error on invocation of $where funciton:\n" + this._scope.getError();
+		throw new Error(ss);
+	} else if ( err !== 0 ) {
+		throw new Error("unknown error in invocation of $where function")
+	}
+
+	return this._scope.__returnValue !== 0;
+};
+
+
+/**
+ *
+ * Call the debugString method
+ * @method toString
+ *
+ */
+proto.debugString = function debugString(level){
+	return this._debugAddSpace( level ) + "$where\n"
+			+ this._debugAddSpace( level + 1 ) + "dbName: " + this._dbName + "\n"
+			+ this._debugAddSpace( level + 1 ) + "code: " + this._code + "\n"
+			+ this._debugAddSpace( level + 1 ) + "scope: " + this._userScope + "\n";
+};
+
+/**
+ *
+ * Return evaluation of comparison result of equivalence.
+ * @method equivalent
+ * @param level
+ *
+ */
+proto.equivalent = function equivalent(other){
+
+	if ( other._matchType != 'MATCH_WHERE' ) {
+		return false;
+	}
+	return this._ns === other._ns &&
+			this._code === other._code &&
+			this._userScope === other._userScope;
+};
+
+
+proto.expressionParserWhereCallbackReal = function expressionParserWhereCallbackReal(where){
+	if ( !this.haveClient() ){
+		return {'code':'NO_CLIENT_CONTEXT', 'description':'no context in $where parsing'};
+	}
+
+	var context = this.cc().getContext();
+	if ( !context ) {
+		return {'code':'BAD_VALUE', 'description':'no ns in $where parsing'};
+	}
+
+	if ( !this.globalScrioptEngine ) {
+		return {'code':'BAD_VALUE', 'description':'no globalScriptEngine in $where parsing'};
+	}
+
+	var exp = new WhereMatchExpression();
+	if ( typeof where === 'string' || typeof where === 'code' ){
+		var s = this.exp.init( ns, where, {} );
+		if ( !s.isOK() ) {
+			return this.StatusWithMatchExpression( s );
+		}
+		return this.StatusWithMatchExpression( this.exp.release() );
+	}
+	return this.StatusWithMatchExpression( {'code':'BAD_VALUE', 'description':'$where got bad type'} );
+};
+
+/**
+ *
+ * Writes a debug string for this object
+ * @method debugString
+ * @param level
+ *
+ */
+proto._debugAddSpace = function _debugAddSpace(level){
+	return new Array( level + 1).join("    ");
+};
+
+/**
+ *
+ * Reset and return the _tagData property
+ * @method resetTag
+ *
+ */
+proto.resetTag = function resetTag(){
+	this.setTag(null);
+};
+
+/**
+ *
+ * Check if the input element matches
+ * @method matchesSingleElement
+ * @param e
+ *
+ */
+proto.matchesSingleElement = function matchesSingleElement(e) {
+	return false;
+};
+
+/**
+ *
+ * clone this instance to a new one
+ * @method shallowClone
+ *
+ */
+proto.shallowClone = function shallowClone(){
+	var e = new WhereMatchExpression(this._txn);
+	e.init(this._dbName, this._code, this._userScope);
+	if ( this.getTag() ){
+		e.setTag(this.getTag().clone());
+	}
+	return e;
+};
+
+
+/*
+TODO: MONGO_INITIALIZER is not impelemented.
+*/

+ 3 - 1
package.json

@@ -12,7 +12,9 @@
     "Kyle P Davis <KDavis@riverainc.com>",
     "Kyle P Davis <KDavis@riverainc.com>",
     "Phil Murray <PMurray@riverainc.com>",
     "Phil Murray <PMurray@riverainc.com>",
     "Spencer Rathbun <SRathbun@riverainc.com>",
     "Spencer Rathbun <SRathbun@riverainc.com>",
-    "Tony Ennis <TEnnis@riverainc.com>"
+    "Tony Ennis <TEnnis@riverainc.com>",
+    "Scott Munday <SMunday@riverainc.com>",
+    "David Aebersold <DAebersold@riverainc.com>"
   ],
   ],
   "main": "./mungedb-aggregate.js",
   "main": "./mungedb-aggregate.js",
   "scripts": {
   "scripts": {

+ 83 - 0
test/lib/pipeline/matcher/WhereMatchExpression.js

@@ -0,0 +1,83 @@
+"use strict";
+var assert = require("assert"),
+	WhereMatchExpression = require("../../../../lib/pipeline/matcher/WhereMatchExpression");
+
+// Mongo supplied no integration tests with WhereMatchExpression
+module.exports = {
+	"WhereMatchExpression": {
+		"should run series of tests": function (){
+			var e = new WhereMatchExpression();
+
+			// MOCK UP MISSING INTEGRATION PIECES
+			// TODO: After all the missing elements are implemented, 
+			// most mocks will not be necessary.
+			e._userScope = {};
+			e._scope= {};
+			e._ns = "ns";
+			e._code = "code";
+
+			e._scope.invoke = function(){};
+			e.getAuthorizationSession = function(){
+				var result = {};
+				result.getAuthenticatedUserNamesToken = function(){};
+				return result;
+			};
+			e.getAuthorizationSession.getAuthenticatedUserNamesToken = function(){};
+			e.globalScriptEngine = {};
+			e.globalScriptEngine.getPooledScope = function(txn, dbName, userToken){
+				var scope = {};
+				scope.createFunction = function( code ){
+					var result = {};
+					return result;
+				};
+				scope.obj = {}
+				scope.fullObject = false;
+				scope.init = function( scope){
+					return {};
+				}
+				scope.invoke = function( func, it, obj, time, bl){
+					return 0;
+				}
+				return scope;
+			};
+
+			var theCode = {};
+			theCode.c_str = function(){};
+
+			var scope = {};
+			scope.getOwned = function(){ return {};};
+			var dbName = "eagle6";
+
+			// Assert we can create
+			var s = e.init(dbName,theCode,scope);
+			assert.strictEqual(s.code, 'OK');
+
+			// Assert we get debugString
+			var debugString = e.debugString(0);
+			assert.strictEqual(debugString.split("\n")[1], '    dbName: eagle6');
+
+			// Assert equivalent
+			var result = e.equivalent("NotEQ");
+			assert.strictEqual(result, false);
+
+			// Assert equivalent of unknown type
+			var other = {};
+			other._matchType = "SOME_UNKNOWN_TYPE";
+			var result = e.equivalent(other);
+			assert.strictEqual(result, false);
+
+			// Assert equivalent of correct type but return false because objects don't match
+			var other = {};
+			other._matchType = "MATCH_WHERE";
+			var result = e.equivalent(other);
+			assert.strictEqual(result, false);
+
+			// Assert equivalent of correct type
+			var result = e.equivalent(e);
+			assert.strictEqual(result, true);
+		}
+	}
+};
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
+