diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js index f5b6dc1a2b..9171d12cbb 100644 --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -2088,4 +2088,60 @@ describe('Parse.Query testing', () => { console.log(error); }); }); + + // #371 + it('should properly interpret a query', (done) => { + var query = new Parse.Query("C1"); + var auxQuery = new Parse.Query("C1"); + query.matchesKeyInQuery("A1", "A2", auxQuery); + query.include("A3"); + query.include("A2"); + query.find().then((result) => { + done(); + }, (err) => { + console.error(err); + fail("should not failt"); + done(); + }) + }); + + it('should properly interpret a query', (done) => { + var user = new Parse.User(); + user.set("username", "foo"); + user.set("password", "bar"); + return user.save().then( (user) => { + var objIdQuery = new Parse.Query("_User").equalTo("objectId", user.id); + var blockedUserQuery = user.relation("blockedUsers").query(); + + var aResponseQuery = new Parse.Query("MatchRelationshipActivityResponse"); + aResponseQuery.equalTo("userA", user); + aResponseQuery.equalTo("userAResponse", 1); + + var bResponseQuery = new Parse.Query("MatchRelationshipActivityResponse"); + bResponseQuery.equalTo("userB", user); + bResponseQuery.equalTo("userBResponse", 1); + + var matchOr = Parse.Query.or(aResponseQuery, bResponseQuery); + var matchRelationshipA = new Parse.Query("_User"); + matchRelationshipA.matchesKeyInQuery("objectId", "userAObjectId", matchOr); + var matchRelationshipB = new Parse.Query("_User"); + matchRelationshipB.matchesKeyInQuery("objectId", "userBObjectId", matchOr); + + + var orQuery = Parse.Query.or(objIdQuery, blockedUserQuery, matchRelationshipA, matchRelationshipB); + var query = new Parse.Query("_User"); + query.doesNotMatchQuery("objectId", orQuery); + return query.find(); + }).then((res) => { + done(); + done(); + }, (err) => { + console.error(err); + fail("should not fail"); + done(); + }); + + + }); + }); diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index a3fbe82ce5..e1416ecb6e 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -291,6 +291,44 @@ describe('Parse.Relation testing', () => { }); }); + it("query on pointer and relation fields with equal", (done) => { + var ChildObject = Parse.Object.extend("ChildObject"); + var childObjects = []; + for (var i = 0; i < 10; i++) { + childObjects.push(new ChildObject({x: i})); + } + + Parse.Object.saveAll(childObjects).then(() => { + var ParentObject = Parse.Object.extend("ParentObject"); + var parent = new ParentObject(); + parent.set("x", 4); + var relation = parent.relation("toChilds"); + relation.add(childObjects[0]); + relation.add(childObjects[1]); + relation.add(childObjects[2]); + + var parent2 = new ParentObject(); + parent2.set("x", 3); + parent2.set("toChild", childObjects[2]); + + var parents = []; + parents.push(parent); + parents.push(parent2); + parents.push(new ParentObject()); + + return Parse.Object.saveAll(parents).then(() => { + var query = new Parse.Query(ParentObject); + query.equalTo("objectId", parent.id); + query.equalTo("toChilds", childObjects[2]); + + return query.find().then((list) => { + equal(list.length, 1, "There should be 1 result"); + done(); + }); + }); + }); + }); + it("or queries on pointer and relation fields", (done) => { var ChildObject = Parse.Object.extend("ChildObject"); var childObjects = []; @@ -335,6 +373,7 @@ describe('Parse.Relation testing', () => { }); }); + it("Get query on relation using un-fetched parent object", (done) => { // Setup data model var Wheel = Parse.Object.extend('Wheel'); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index ec0fb1f69c..683b9be053 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -417,9 +417,8 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem relatedIds = [query[key].objectId]; } return this.owningIds(className, key, relatedIds).then((ids) => { - delete query[key]; - query.objectId = Object.assign({'$in': []}, query.objectId); - query.objectId['$in'] = query.objectId['$in'].concat(ids); + delete query[key]; + this.addInObjectIdsIds(ids, query); return Promise.resolve(query); }); } @@ -448,15 +447,23 @@ DatabaseController.prototype.reduceRelationKeys = function(className, query) { relatedTo.key, relatedTo.object.objectId).then((ids) => { delete query['$relatedTo']; - query.objectId = query.objectId || {}; - let queryIn = query.objectId['$in'] || []; - queryIn = queryIn.concat(ids); - query['objectId'] = {'$in': queryIn}; + this.addInObjectIdsIds(ids, query); return this.reduceRelationKeys(className, query); }); } }; +DatabaseController.prototype.addInObjectIdsIds = function(ids, query) { + if (typeof query.objectId == 'string') { + query.objectId = {'$in': [query.objectId]}; + } + query.objectId = query.objectId || {}; + let queryIn = [].concat(query.objectId['$in'] || [], ids || []); + // make a set and spread to remove duplicates + query.objectId = {'$in': [...new Set(queryIn)]}; + return query; +} + // Runs a query on the database. // Returns a promise that resolves to a list of items. // Options: diff --git a/src/RestQuery.js b/src/RestQuery.js index e68ec16f31..5cd2df52cb 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -271,11 +271,11 @@ RestQuery.prototype.replaceSelect = function() { // The select value must have precisely two keys - query and key var selectValue = selectObject['$select']; + // iOS SDK don't send where if not set, let it pass if (!selectValue.query || !selectValue.key || typeof selectValue.query !== 'object' || !selectValue.query.className || - !selectValue.query.where || Object.keys(selectValue).length !== 2) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $select');