WhereMatchExpression.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. "use strict";
  2. var WhereMatchExpression = module.exports = function WhereMatchExpression( txn ){
  3. this._txn = txn;
  4. this._matchType = 'MATCH_WHERE';
  5. }, klass = WhereMatchExpression, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  6. // DEPENDENCIES
  7. var errors = require("../../Errors.js"),
  8. ErrorCodes = errors.ErrorCodes,
  9. MatchExpression = require("./MatchExpression.js"),
  10. MatchExpressionParser = require("./MatchExpressionParser.js");
  11. proto._txn = undefined;
  12. proto._func = 0;
  13. proto._dbName = undefined;
  14. proto._ns = undefined;
  15. proto._code = undefined;
  16. proto._userScope = undefined;
  17. proto._scope = undefined;
  18. /**
  19. *
  20. * Initialize the necessary items
  21. * @method init
  22. * @param dbName
  23. * @param theCode
  24. * @param scope
  25. *
  26. */
  27. proto.init = function init(dbName, theCode, scope) {
  28. if ( dbName === undefined ) {
  29. return {'code':'BAD_VALUE', 'description':'ns for $where cannot be empty'};
  30. }
  31. if ( theCode === undefined ) {
  32. return {'code':'BAD_VALUE', 'description':'code for $where cannot be empty'};
  33. }
  34. this._dbName = dbName;
  35. this._code = theCode;
  36. // TODO: Not implementing for now.
  37. this._userScope = scope.getOwned();
  38. var userToken = this.getAuthorizationSession().getAuthenticatedUserNamesToken();
  39. this._scope = this.globalScriptEngine.getPooledScope(this._txn, this._dbName, "where" + userToken);
  40. this._func = this._scope.createFunction( this._code.c_str() );
  41. if ( !this._func) {
  42. return {'code':'BAD_VALUE', 'description':'$where compile error'};
  43. }
  44. return {'code':'OK'};
  45. };
  46. /**
  47. *
  48. * Matches the necessary items
  49. * @method matches
  50. * @param doc
  51. * @param details
  52. *
  53. */
  54. proto.matches = function matches(doc, details) {
  55. var obj = JSON.stringify(doc);
  56. if ( this._userScope === undefined ){
  57. this._scope.init( this._userScope);
  58. }
  59. this._scope.obj = obj;
  60. this._scope.fullObject = true;
  61. var err = this._scope.invoke( this._func, 0, obj, 1000 * 60, false);
  62. if ( err == -3) { // INVOKE_ERROR
  63. var ss = "error on invocation of $where funciton:\n" + this._scope.getError();
  64. throw new Error(ss);
  65. } else if ( err !== 0 ) {
  66. throw new Error("unknown error in invocation of $where function")
  67. }
  68. return this._scope.__returnValue !== 0;
  69. };
  70. /**
  71. *
  72. * Call the debugString method
  73. * @method toString
  74. *
  75. */
  76. proto.debugString = function debugString(level){
  77. return this._debugAddSpace( level ) + "$where\n"
  78. + this._debugAddSpace( level + 1 ) + "dbName: " + this._dbName + "\n"
  79. + this._debugAddSpace( level + 1 ) + "code: " + this._code + "\n"
  80. + this._debugAddSpace( level + 1 ) + "scope: " + this._userScope + "\n";
  81. };
  82. /**
  83. *
  84. * Return evaluation of comparison result of equivalence.
  85. * @method equivalent
  86. * @param level
  87. *
  88. */
  89. proto.equivalent = function equivalent(other){
  90. if ( other._matchType != 'MATCH_WHERE' ) {
  91. return false;
  92. }
  93. return this._ns === other._ns &&
  94. this._code === other._code &&
  95. this._userScope === other._userScope;
  96. };
  97. proto.expressionParserWhereCallbackReal = function expressionParserWhereCallbackReal(where){
  98. if ( !this.haveClient() ){
  99. return {'code':'NO_CLIENT_CONTEXT', 'description':'no context in $where parsing'};
  100. }
  101. var context = this.cc().getContext();
  102. if ( !context ) {
  103. return {'code':'BAD_VALUE', 'description':'no ns in $where parsing'};
  104. }
  105. if ( !this.globalScrioptEngine ) {
  106. return {'code':'BAD_VALUE', 'description':'no globalScriptEngine in $where parsing'};
  107. }
  108. var exp = new WhereMatchExpression();
  109. if ( typeof where === 'string' || typeof where === 'code' ){
  110. var s = this.exp.init( ns, where, {} );
  111. if ( !s.isOK() ) {
  112. return this.StatusWithMatchExpression( s );
  113. }
  114. return this.StatusWithMatchExpression( this.exp.release() );
  115. }
  116. return this.StatusWithMatchExpression( {'code':'BAD_VALUE', 'description':'$where got bad type'} );
  117. };
  118. /**
  119. *
  120. * Writes a debug string for this object
  121. * @method debugString
  122. * @param level
  123. *
  124. */
  125. proto._debugAddSpace = function _debugAddSpace(level){
  126. return new Array( level + 1).join(" ");
  127. };
  128. /**
  129. *
  130. * Reset and return the _tagData property
  131. * @method resetTag
  132. *
  133. */
  134. proto.resetTag = function resetTag(){
  135. this.setTag(null);
  136. };
  137. /**
  138. *
  139. * Check if the input element matches
  140. * @method matchesSingleElement
  141. * @param e
  142. *
  143. */
  144. proto.matchesSingleElement = function matchesSingleElement(e) {
  145. return false;
  146. };
  147. /**
  148. *
  149. * clone this instance to a new one
  150. * @method shallowClone
  151. *
  152. */
  153. proto.shallowClone = function shallowClone(){
  154. var e = new WhereMatchExpression(this._txn);
  155. e.init(this._dbName, this._code, this._userScope);
  156. if ( this.getTag() ){
  157. e.setTag(this.getTag().clone());
  158. }
  159. return e;
  160. };
  161. /*
  162. TODO: MONGO_INITIALIZER is not impelemented.
  163. */