Matcher2.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. "use strict";
  2. // Autogenerated by cport.py on 2013-09-17 14:37
  3. var Matcher2 = module.exports = function Matcher2(pattern, nested){
  4. // File: matcher.cpp lines: 83-92
  5. this._pattern = pattern;
  6. var result = this.parser.parse(pattern);
  7. if (result.code != ErrorCodes.OK)
  8. return {code:16810, description:"bad query: " + result};
  9. this._expression = result.result;
  10. // File: matcher.cpp lines: 94-102
  11. /*
  12. var indexExpression = this.spliceForIndex(constrainIndexKey, docMatcher, this._spliceInfo);
  13. if (indexExpression) {
  14. this._expression = indexExpression;
  15. }
  16. */
  17. }, klass = Matcher2, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  18. // DEPENDENCIES
  19. var errors = require("../../Errors.js"),
  20. ErrorCodes = errors.ErrorCodes,
  21. MatchExpression = require("./MatchExpression.js"),
  22. MatchExpressionParser = require("./MatchExpressionParser.js"),
  23. FalseMatchExpression = require("./FalseMatchExpression.js"),
  24. ComparisonMatchExpression = require("./ComparisonMatchExpression.js"),
  25. InMatchExpression = require("./InMatchExpression.js"),
  26. AndMatchExpression = require("./AndMatchExpression.js"),
  27. OrMatchExpression = require("./OrMatchExpression.js"),
  28. IndexKeyMatchableDocument = require('./IndexKeyMatchableDocument.js'),
  29. ListOfMatchExpression = require('./ListOfMatchExpression.js'),
  30. LeafMatchExpression = require("./LeafMatchExpression.js");
  31. // File: matcher.h lines: 82-82
  32. proto._expression = undefined;
  33. // File: matcher.h lines: 80-80
  34. proto._indexKey = undefined;
  35. // File: matcher.h lines: 79-79
  36. proto._pattern = undefined;
  37. // File: matcher.h lines: 84-84
  38. proto._spliceInfo = undefined;
  39. proto.parser = new MatchExpressionParser();
  40. /**
  41. *
  42. * This documentation was automatically generated. Please update when you touch this function.
  43. * @method _spliceForIndex
  44. * @param
  45. *
  46. */
  47. proto._spliceForIndex = function _spliceForIndex(keys, full, spliceInfo){
  48. // File: matcher.cpp lines: 236-380
  49. var dup, i, obj, lme;
  50. switch (full) {
  51. case MatchExpression.ALWAYS_FALSE:
  52. return new FalseMatchExpression();
  53. case MatchExpression.GEO_NEAR:
  54. case MatchExpression.NOT:
  55. case MatchExpression.NOR:
  56. // maybe?
  57. return null;
  58. case MatchExpression.OR:
  59. case MatchExpression.AND:
  60. dup = new ListOfMatchExpression();
  61. for (i = 0; i < full.numChildren(); i++) {
  62. var sub = this._spliceForIndex(keys, full.getChild(i), spliceInfo);
  63. if (!sub)
  64. continue;
  65. if (!dup.get()) {
  66. if (full.matchType() == MatchExpression.AND)
  67. dup.reset(new AndMatchExpression());
  68. else
  69. dup.reset(new OrMatchExpression());
  70. }
  71. dup.add(sub);
  72. }
  73. if (dup.get()) {
  74. if (full.matchType() == MatchExpression.OR && dup.numChildren() != full.numChildren()) {
  75. // TODO: I think this should actuall get a list of all the fields
  76. // and make sure that's the same
  77. // with an $or, have to make sure its all or nothing
  78. return null;
  79. }
  80. return dup.release();
  81. }
  82. return null;
  83. case MatchExpression.EQ:
  84. var cmp = new ComparisonMatchExpression(full);
  85. if (cmp.getRHS().type() == Array) {
  86. // need to convert array to an $in
  87. if (!keys.count(cmp.path().toString()))
  88. return null;
  89. var newIn = new InMatchExpression();
  90. newIn.init(cmp.path());
  91. if (newIn.getArrayFilterEntries().addEquality(cmp.getRHS()).isOK())
  92. return null;
  93. if (cmp.getRHS().Obj().isEmpty())
  94. newIn.getArrayFilterEntries().addEquality(undefined);
  95. obj = cmp.getRHS().Obj();
  96. for(i in obj) {
  97. var s = newIn.getArrayFilterEntries().addEquality( obj[i].next() );
  98. if (s.code != ErrorCodes.OK)
  99. return null;
  100. }
  101. return newIn.release();
  102. }
  103. else if (cmp.getRHS().type() === null) {
  104. //spliceInfo.hasNullEquality = true;
  105. return null;
  106. }
  107. break;
  108. case MatchExpression.LTE:
  109. case MatchExpression.LT:
  110. case MatchExpression.GT:
  111. case MatchExpression.GTE:
  112. cmp = new ComparisonMatchExpression(full);
  113. if ( cmp.getRHS().type() === null) {
  114. // null and indexes don't play nice
  115. //spliceInfo.hasNullEquality = true;
  116. return null;
  117. }
  118. break;
  119. case MatchExpression.REGEX:
  120. case MatchExpression.MOD:
  121. lme = new LeafMatchExpression(full);
  122. if (!keys.count(lme.path().toString()))
  123. return null;
  124. return lme.shallowClone();
  125. case MatchExpression.MATCH_IN:
  126. lme = new LeafMatchExpression(full);
  127. if (!keys.count(lme.path().toString()))
  128. return null;
  129. var cloned = new InMatchExpression(lme.shallowClone());
  130. if (cloned.getArrayFilterEntries().hasEmptyArray())
  131. cloned.getArrayFilterEntries().addEquality(undefined);
  132. // since { $in : [[1]] } matches [1], need to explode
  133. for (i = cloned.getArrayFilterEntries().equalities().begin(); i != cloned.getArrayFilterEntries().equalities().end(); ++i) {
  134. var x = cloned[i];
  135. if (x.type() == Array) {
  136. for(var j in x) {
  137. cloned.getArrayFilterEntries().addEquality(x[j]);
  138. }
  139. }
  140. }
  141. return cloned;
  142. case MatchExpression.ALL:
  143. // TODO: convert to $in
  144. return null;
  145. case MatchExpression.ELEM_MATCH_OBJECT:
  146. case MatchExpression.ELEM_MATCH_VALUE:
  147. // future
  148. return null;
  149. case MatchExpression.GEO:
  150. case MatchExpression.SIZE:
  151. case MatchExpression.EXISTS:
  152. case MatchExpression.NIN:
  153. case MatchExpression.TYPE_OPERATOR:
  154. case MatchExpression.ATOMIC:
  155. case MatchExpression.WHERE:
  156. // no go
  157. return null;
  158. }
  159. return null;
  160. };
  161. /**
  162. *
  163. * This documentation was automatically generated. Please update when you touch this function.
  164. * @method atomic
  165. * @param
  166. *
  167. */
  168. proto.atomic = function atomic(){
  169. // File: matcher.cpp lines: 120-133
  170. if (!this._expression)
  171. return false;
  172. if (this._expression.matchType() == MatchExpression.ATOMIC)
  173. return true;
  174. // we only go down one level
  175. for (var i = 0; i < this._expression.numChildren(); i++) {
  176. if (this._expression.getChild(i).matchType() == MatchExpression.ATOMIC)
  177. return true;
  178. }
  179. return false;
  180. };
  181. /**
  182. *
  183. * This documentation was automatically generated. Please update when you touch this function.
  184. * @method getQuery
  185. * @param
  186. *
  187. */
  188. proto.getQuery = function getQuery(){
  189. // File: matcher.h lines: 65-64
  190. return this._pattern;
  191. };
  192. /**
  193. *
  194. * This documentation was automatically generated. Please update when you touch this function.
  195. * @method hasExistsFalse
  196. * @param
  197. *
  198. */
  199. proto.hasExistsFalse = function hasExistsFalse(){
  200. // File: matcher.cpp lines: 172-180
  201. if (this._spliceInfo.hasNullEquality) {
  202. // { a : NULL } is very dangerous as it may not got indexed in some cases
  203. // so we just totally ignore
  204. return true;
  205. }
  206. return this._isExistsFalse(this._expression.get(), false, this._expression.matchType() == MatchExpression.AND ? -1 : 0);
  207. };
  208. /**
  209. *
  210. * This documentation was automatically generated. Please update when you touch this function.
  211. * @method keyMatch
  212. * @param
  213. *
  214. */
  215. proto.keyMatch = function keyMatch(docMatcher){
  216. // File: matcher.cpp lines: 199-206
  217. if (!this._expression)
  218. return docMatcher._expression.get() === null;
  219. if (!docMatcher._expression)
  220. return false;
  221. if (this._spliceInfo.hasNullEquality)
  222. return false;
  223. return this._expression.equivalent(docMatcher._expression.get());
  224. };
  225. /**
  226. *
  227. * This documentation was automatically generated. Please update when you touch this function.
  228. * @method matches
  229. * @param
  230. *
  231. */
  232. proto.matches = function matches(doc, details){
  233. // File: matcher.cpp lines: 105-116
  234. if (!this._expression)
  235. return true;
  236. if (this._indexKey == {})
  237. return this._expression.matchesBSON(doc, details);
  238. if ((doc != {}) && (Object.keys(doc)[0]))
  239. return this._expression.matchesBSON(doc, details);
  240. var mydoc = new IndexKeyMatchableDocument(this._indexKey, doc);
  241. return this._expression.matches(mydoc, details);
  242. };
  243. /**
  244. *
  245. * This documentation was automatically generated. Please update when you touch this function.
  246. * @method singleSimpleCriterion
  247. * @param
  248. *
  249. */
  250. proto.singleSimpleCriterion = function singleSimpleCriterion(){
  251. // File: matcher.cpp lines: 184-196
  252. if (!this._expression)
  253. return false;
  254. if (this._expression.matchType() == MatchExpression.EQ)
  255. return true;
  256. if (this._expression.matchType() == MatchExpression.AND && this._expression.numChildren() == 1 && this._expression.getChild(0).matchType() == MatchExpression.EQ)
  257. return true;
  258. return false;
  259. };
  260. /**
  261. *
  262. * This documentation was automatically generated. Please update when you touch this function.
  263. * @method spliceForIndex
  264. * @param
  265. *
  266. */
  267. proto.spliceForIndex = function spliceForIndex(key, full, spliceInfo){
  268. // File: matcher.cpp lines: 209-217
  269. var keys = [],
  270. e, i;
  271. for (i in key) {
  272. e = key[i];
  273. keys.insert(e.fieldName());
  274. }
  275. return this._spliceForIndex(keys, full, spliceInfo);
  276. };
  277. /**
  278. *
  279. * This documentation was automatically generated. Please update when you touch this function.
  280. * @method toString
  281. * @param
  282. *
  283. */
  284. proto.toString = function toString(){
  285. // File: matcher.h lines: 66-65
  286. return this._pattern.toString();
  287. };