Commit 7cb37ddf authored by Dian Fay's avatar Dian Fay
Browse files

feat: support $and and $or criteria keys

parent 30697aac
Loading
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ Readable.prototype.where = function (conditions, params = [], options = {}) {
 * Build a disjunction (logical OR).
 *
 * @param {Object} criteria - The criteria object representing the JOIN
 * conditions. May be nested with `or`, just as ordinary criteria objects.
 * conditions. May be nested with `$or`, just as ordinary criteria objects.
 * @param {Number} offset - Offset prepared statement parameter ordinals
 * @param {Symbol} kind - forJoin, forWhere, or forDoc.
 * @return {String} The JOIN condition text, to be stored and interpolated into
@@ -290,7 +290,7 @@ Readable.prototype.disjoin = function (criteria, offset, kind, ...args) {
 * Build a conjunction (logical AND).
 *
 * @param {Object} criteria - The criteria object representing the JOIN
 * conditions. May be nested with `or`, just as ordinary criteria objects.
 * conditions. May be nested with `$or`, just as ordinary criteria objects.
 * @param {Number} offset - Offset prepared statement parameter ordinals
 * @param {Symbol} kind - forJoin, forWhere, or forDoc.
 * @return {String} The JOIN condition text, to be stored and interpolated into
@@ -298,14 +298,16 @@ Readable.prototype.disjoin = function (criteria, offset, kind, ...args) {
 */
Readable.prototype.conjoin = function (criteria, offset, kind, ...args) {
  return _.reduce(criteria, (conjunction, val, key) => {
    if (key === 'or') {
    // TODO un-$ed names are officially deprecated but may or may not ever be
    // practical to remove
    if (['$or', 'or'].indexOf(key) > -1) {
      const disjunction = this.disjoin(val, conjunction.offset + conjunction.params.length, kind, ...args);

      conjunction.params = conjunction.params.concat(disjunction.params);
      conjunction.predicates.push(`(${disjunction.predicates.join(' OR ')})`);

      return conjunction;
    } else if (key === 'and') {
    } else if (['$and', 'and'].indexOf(key) > -1) {
      const predicates = []; // track subconjunction predicates separately since they're grouped together

      conjunction = _.reduce(val, (c, subconditions) => {
@@ -389,9 +391,9 @@ Readable.prototype.conjoin = function (criteria, offset, kind, ...args) {
 *
 * @param {Object} criteria - Query criteria mapping column names (optionally
 * including operation eg 'my_field <>') to the parameter values. Predicates
 * generated from a criteria object are joined together with `and`; an `or` key
 * denotes an array of nested criteria objects, the collected predicates from
 * each of which are parenthesized and joined with `or`.
 * generated from a criteria object are joined together with `$and`; an `$or`
 * key denotes an array of nested criteria objects, the collected predicates
 * from each of which are parenthesized and joined with `$or`.
 * @param {Number} offset - Added to the token index value in the prepared
 * statement (with offset 0, parameters will start $1, $2, $3).
 * @param {Symbol} kind - forJoin, forWhere, or forDoc.
+8 −0
Original line number Diff line number Diff line
@@ -132,6 +132,14 @@ describe('find', function () {
        assert.equal(res[0].id, 1);
      });
    });

    it('applies subcriteria with $or', function () {
      return db.products.find({$or: [{'id <': 2}, {'id >=': 4}]}).then(res => assert.lengthOf(res, 2));
    });

    it('applies subcriteria with $and', function () {
      return db.products.find({$and: [{'id <': 2}, {'id >=': 4}]}).then(res => assert.lengthOf(res, 0));
    });
  });

  describe('pattern-matching queries', function () {