diff --git a/src/OfflineQuery.js b/src/OfflineQuery.js index 46167a586..0f03d3e10 100644 --- a/src/OfflineQuery.js +++ b/src/OfflineQuery.js @@ -308,11 +308,11 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { for (const condition in constraints) { compareTo = constraints[condition]; - if (compareTo.__type) { + if (compareTo && compareTo.__type) { compareTo = decode(compareTo); } // is it a $relativeTime? convert to date - if (compareTo['$relativeTime']) { + if (compareTo && compareTo['$relativeTime']) { const parserResult = relativeTimeToDate(compareTo['$relativeTime']); if (parserResult.status !== 'success') { throw new ParseError( @@ -327,12 +327,47 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { toString.call(compareTo) === '[object Date]' || (typeof compareTo === 'string' && new Date(compareTo) !== 'Invalid Date' && - !isNaN(new Date(compareTo))) + !isNaN(new Date(compareTo)) && + new Date(compareTo).toISOString() === compareTo) ) { object[key] = new Date(object[key].iso ? object[key].iso : object[key]); } switch (condition) { + case '$eq': { + if (typeof compareTo !== 'object') { + // Equality (or Array contains) cases + if (Array.isArray(object[key])) { + if (object[key].indexOf(constraints[condition]) === -1) { + return false; + } + break; + } + if (object[key] !== compareTo) { + return false; + } + break; + } else { + if (compareTo && constraints[condition].__type === 'Pointer') { + if ( + !equalObjectsGeneric(object[key], constraints[condition], function (obj, ptr) { + return ( + typeof obj !== 'undefined' && + ptr.className === obj.className && + ptr.objectId === obj.objectId + ); + }) + ) { + return false; + } + break; + } + if (!equalObjects(decode(object[key]), compareTo)) { + return false; + } + } + break; + } case '$lt': if (object[key] >= compareTo) { return false; diff --git a/src/ParseQuery.js b/src/ParseQuery.js index fe5c6f0ea..c6ffb4959 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -1222,7 +1222,8 @@ class ParseQuery { return this.doesNotExist(key); } - this._where[key] = encode(value, false, true); + // this._where[key] = encode(value, false, true); + this._addCondition(key, '$eq', value); return this; } diff --git a/src/__tests__/Cloud-test.js b/src/__tests__/Cloud-test.js index b65bff268..52245edb5 100644 --- a/src/__tests__/Cloud-test.js +++ b/src/__tests__/Cloud-test.js @@ -301,7 +301,9 @@ describe('CloudController', () => { expect(data).toEqual({ limit: 1, where: { - objectId: 'jobId1234', + objectId: { + $eq: 'jobId1234', + }, }, }); expect(options.useMasterKey).toBe(true); @@ -323,7 +325,9 @@ describe('CloudController', () => { expect(data).toEqual({ limit: 1, where: { - objectId: 'pushId1234', + objectId: { + $eq: 'pushId1234', + }, }, }); expect(options.useMasterKey).toBe(true); @@ -345,7 +349,9 @@ describe('CloudController', () => { expect(data).toEqual({ limit: 1, where: { - objectId: 'pushId1234', + objectId: { + $eq: 'pushId1234', + }, }, }); expect(options.useMasterKey).toBe(false); diff --git a/src/__tests__/LiveQueryClient-test.js b/src/__tests__/LiveQueryClient-test.js index 4329bcd01..24be2edee 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -803,7 +803,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value', + key: { + $eq: 'value', + }, }, }, }); @@ -842,7 +844,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value', + key: { + $eq: 'value', + }, }, }, }); @@ -921,7 +925,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value', + key: { + $eq: 'value', + }, }, }, }); @@ -956,7 +962,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value', + key: { + $eq: 'value', + }, }, }, }); diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 89150dc03..449e98b8f 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -119,7 +119,9 @@ describe('ParseQuery', () => { q.equalTo('size', 'medium'); expect(q.toJSON()).toEqual({ where: { - size: 'medium', + size: { + $eq: 'medium', + }, }, }); @@ -127,7 +129,9 @@ describe('ParseQuery', () => { q.equalTo('size', 'small'); expect(q.toJSON()).toEqual({ where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); @@ -136,6 +140,7 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { size: { + $eq: 'small', $exists: false, }, }, @@ -146,8 +151,13 @@ describe('ParseQuery', () => { q.equalTo({ size, stock }); expect(q.toJSON()).toEqual({ where: { - size: 'medium', - stock: true, + size: { + $eq: 'medium', + $exists: false, + }, + stock: { + $eq: true, + }, }, }); }); @@ -463,7 +473,9 @@ describe('ParseQuery', () => { $inQuery: { className: 'Item', where: { - inStock: 0, + inStock: { + $eq: 0, + }, }, }, }, @@ -483,7 +495,9 @@ describe('ParseQuery', () => { $notInQuery: { className: 'Item', where: { - inStock: 0, + inStock: { + $eq: 0, + }, }, }, }, @@ -505,7 +519,9 @@ describe('ParseQuery', () => { query: { className: 'Item', where: { - inStock: 0, + inStock: { + $eq: 0, + }, }, }, }, @@ -528,7 +544,9 @@ describe('ParseQuery', () => { query: { className: 'Item', where: { - inStock: 0, + inStock: { + $eq: 0, + }, }, }, }, @@ -807,6 +825,36 @@ describe('ParseQuery', () => { }); }); + it('can combine other clauses with equalTo', () => { + const q = new ParseQuery('Item'); + q.exists('inStock'); + q.equalTo('inStock', null); + + expect(q.toJSON()).toEqual({ + where: { + inStock: { + $eq: null, + $exists: true, + }, + }, + }); + }); + + it('can combine equalTo clause with any other clause', () => { + const q = new ParseQuery('Item'); + q.equalTo('arrayField', ['a', 'b']); + q.exists('arrayField'); + + expect(q.toJSON()).toEqual({ + where: { + arrayField: { + $eq: ['a', 'b'], + $exists: true, + }, + }, + }); + }); + it('can specify ordering', () => { const q = new ParseQuery('Item'); q.greaterThan('inStock', 0).ascending('createdAt'); @@ -950,7 +998,9 @@ describe('ParseQuery', () => { q.equalTo('name', 'Product 5'); expect(q.toJSON()).toEqual({ where: { - name: 'Product 5', + name: { + $eq: 'Product 5', + }, }, skip: 4, }); @@ -1146,7 +1196,7 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.or(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $or: [{ size: 'medium' }, { size: 'large' }], + $or: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); @@ -1155,7 +1205,7 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.or(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $or: [{ size: 'medium' }, { size: 'large' }], + $or: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); }); @@ -1172,7 +1222,7 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.and(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $and: [{ size: 'medium' }, { size: 'large' }], + $and: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); @@ -1181,7 +1231,7 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.and(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $and: [{ size: 'medium' }, { size: 'large' }], + $and: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); }); @@ -1198,7 +1248,7 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [{ size: 'medium' }, { size: 'large' }], + $nor: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); @@ -1207,7 +1257,7 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [{ size: 'medium' }, { size: 'large' }], + $nor: [{ size: { $eq: 'medium' } }, { size: { $eq: 'large' } }], }, }); }); @@ -1220,7 +1270,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1253,7 +1305,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -1284,7 +1338,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ explain: true, where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1318,7 +1374,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I27', + objectId: { + $eq: 'I27', + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1386,7 +1444,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I28', + objectId: { + $eq: 'I28', + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1420,7 +1480,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I27', + objectId: { + $eq: 'I27', + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -1451,7 +1513,9 @@ describe('ParseQuery', () => { limit: 0, count: 1, where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1480,7 +1544,9 @@ describe('ParseQuery', () => { limit: 0, count: 1, where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -1673,7 +1739,9 @@ describe('ParseQuery', () => { include: '*', hint: '_id_', where: { - arrayField: ['a', 'b'], + arrayField: { + $eq: ['a', 'b'], + }, size: { $in: ['small', 'medium'], }, @@ -1683,12 +1751,14 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5, + stars: { $eq: 5 }, }, }, }, }, - valid: true, + valid: { + $eq: true, + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1809,12 +1879,16 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5, + stars: { + $eq: 5, + }, }, }, }, }, - valid: true, + valid: { + $eq: true, + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1879,12 +1953,16 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5, + stars: { + $eq: 5, + }, }, }, }, }, - valid: true, + valid: { + $eq: true, + }, }, }); expect(options.requestTask).toBeDefined(); @@ -1928,7 +2006,9 @@ describe('ParseQuery', () => { size: { $in: ['small', 'medium'], }, - valid: true, + valid: { + $eq: true, + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -1979,7 +2059,9 @@ describe('ParseQuery', () => { size: { $in: ['small', 'medium'], }, - valid: true, + valid: { + $eq: true, + }, }, hint: '_id_', }); @@ -2528,7 +2610,9 @@ describe('ParseQuery', () => { order: 'a,b,c', skip: 4, where: { - size: 'medium', + size: { + $eq: 'medium', + }, }, }); }); @@ -2541,7 +2625,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -2569,7 +2655,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small', + size: { + $eq: 'small', + }, }, }); expect(options.useMasterKey).toEqual(true); @@ -2600,7 +2688,9 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small', + size: { + $eq: 'small', + }, }, hint: '_id_', });