From e00112ec3cff1b6de0e8b352160fb6bf78892858 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Tue, 15 Mar 2016 15:19:41 -0400 Subject: [PATCH 1/3] adds failing test for resolution --- spec/ParseRelation.spec.js | 81 +++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index 403628ed53..ae911967e4 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -237,7 +237,7 @@ describe('Parse.Relation testing', () => { success: function(list) { equal(list.length, 1, "There should be only one result"); equal(list[0].id, parent2.id, - "Should have gotten back the right result"); + "Should have gotten back the right result"); done(); } }); @@ -246,7 +246,7 @@ describe('Parse.Relation testing', () => { } }); }); - + it("queries on relation fields with multiple ins", (done) => { var ChildObject = Parse.Object.extend("ChildObject"); var childObjects = []; @@ -268,7 +268,7 @@ describe('Parse.Relation testing', () => { relation2.add(childObjects[4]); relation2.add(childObjects[5]); relation2.add(childObjects[6]); - + var otherChild2 = parent2.relation("otherChild"); otherChild2.add(childObjects[0]); otherChild2.add(childObjects[1]); @@ -290,7 +290,7 @@ describe('Parse.Relation testing', () => { done(); }); }); - + it("query on pointer and relation fields with equal", (done) => { var ChildObject = Parse.Object.extend("ChildObject"); var childObjects = []; @@ -306,21 +306,21 @@ describe('Parse.Relation testing', () => { 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(); @@ -328,7 +328,7 @@ describe('Parse.Relation testing', () => { }); }); }); - + it("query on pointer and relation fields with equal bis", (done) => { var ChildObject = Parse.Object.extend("ChildObject"); var childObjects = []; @@ -344,23 +344,23 @@ describe('Parse.Relation testing', () => { relation.add(childObjects[0]); relation.add(childObjects[1]); relation.add(childObjects[2]); - + var parent2 = new ParentObject(); parent2.set("x", 3); parent2.relation("toChilds").add(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", parent2.id); // childObjects[2] is in 2 relations // before the fix, that woul yield 2 results query.equalTo("toChilds", childObjects[2]); - + return query.find().then((list) => { equal(list.length, 1, "There should be 1 result"); done(); @@ -368,7 +368,7 @@ describe('Parse.Relation testing', () => { }); }); }); - + it("or queries on pointer and relation fields", (done) => { var ChildObject = Parse.Object.extend("ChildObject"); var childObjects = []; @@ -384,16 +384,16 @@ describe('Parse.Relation testing', () => { 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 query1 = new Parse.Query(ParentObject); query1.containedIn("toChilds", [childObjects[2]]); @@ -501,5 +501,50 @@ describe('Parse.Relation testing', () => { }); }); -}); + notWorking('should properly get related objects with unfetched queries', (done) => { + let objects = []; + let owners = []; + let allObjects = []; + // Build 10 Objects and 10 owners + while (objects.length != 10) { + let object = new Parse.Object('AnObject'); + object.set({ + index: objects.length, + even: objects.length % 2 == 0 + }); + objects.push(object); + let owner = new Parse.Object('AnOwner'); + owners.push(owner); + allObjects.push(object); + allObjects.push(owner); + } + + let anotherOwner = new Parse.Object('AnotherOwner'); + return Parse.Object.saveAll(allObjects.concat([anotherOwner])).then(() => { + // put all the AnObject into the anotherOwner relationKey + anotherOwner.relation('relationKey').add(objects); + // Set each object[i] into owner[i]; + owners.forEach((owner,i) => { + owner.set('key', objects[i]); + }); + return Parse.Object.saveAll(owners.concat([anotherOwner])); + }).then(() => { + // Query on the relation of another owner + let object = new Parse.Object('AnotherOwner'); + object.id = anotherOwner.id; + let relationQuery = object.relation('relationKey').query(); + // Just get the even ones + relationQuery.equalTo('even', true); + // Make the query on anOwner + let query = new Parse.Query('AnOwner'); + // where key match the relation query. + query.matchesQuery('key', relationQuery); + query.include('key'); + return query.find(); + }).then((results) => { + expect(results.length).toBe(5); + done(); + }); + }); +}); From 3ed3982e0e3efa245809b82a12f7fe9b7f7f6e06 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Tue, 15 Mar 2016 16:19:12 -0400 Subject: [PATCH 2/3] Fixes bug affecting matchesQuery and doesNotMatchQuery on relations on unfetched objects --- spec/ParseRelation.spec.js | 28 ++++++++++++++++++++++++++-- src/RestQuery.js | 21 +++++++++++++-------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index ae911967e4..434e919229 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -1,3 +1,4 @@ +'use strict'; // This is a port of the test suite: // hungry/js/test/parse_relation_test.js @@ -501,7 +502,7 @@ describe('Parse.Relation testing', () => { }); }); - notWorking('should properly get related objects with unfetched queries', (done) => { + it('should properly get related objects with unfetched queries', (done) => { let objects = []; let owners = []; let allObjects = []; @@ -544,7 +545,30 @@ describe('Parse.Relation testing', () => { return query.find(); }).then((results) => { expect(results.length).toBe(5); + results.forEach((result) => { + expect(result.get('key').get('even')).toBe(true); + }); + return Promise.resolve(); + }).then(() => { + console.log(''); + // Query on the relation of another owner + let object = new Parse.Object('AnotherOwner'); + object.id = anotherOwner.id; + let relationQuery = object.relation('relationKey').query(); + // Just get the even ones + relationQuery.equalTo('even', true); + // Make the query on anOwner + let query = new Parse.Query('AnOwner'); + // where key match the relation query. + query.doesNotMatchQuery('key', relationQuery); + query.include('key'); + return query.find(); + }).then((results) => { + expect(results.length).toBe(5); + results.forEach((result) => { + expect(result.get('key').get('even')).toBe(false); + }); done(); - }); + }) }); }); diff --git a/src/RestQuery.js b/src/RestQuery.js index 0ddc7b4ba7..4c5bb0b736 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -20,7 +20,6 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}) { this.className = className; this.restWhere = restWhere; this.response = null; - this.findOptions = {}; if (!this.auth.isMaster) { this.findOptions.acl = this.auth.user ? [this.auth.user.id] : null; @@ -205,15 +204,19 @@ RestQuery.prototype.replaceInQuery = function() { 'improper usage of $inQuery'); } + let additionalOptions = { + redirectClassNameForKey: inQueryValue.redirectClassNameForKey + }; + var subquery = new RestQuery( this.config, this.auth, inQueryValue.className, - inQueryValue.where); + inQueryValue.where, additionalOptions); return subquery.execute().then((response) => { var values = []; for (var result of response.results) { values.push({ __type: 'Pointer', - className: inQueryValue.className, + className: subquery.className, objectId: result.objectId }); } @@ -223,7 +226,6 @@ RestQuery.prototype.replaceInQuery = function() { } else { inQueryObject['$in'] = values; } - // Recurse to repeat return this.replaceInQuery(); }); @@ -246,15 +248,19 @@ RestQuery.prototype.replaceNotInQuery = function() { 'improper usage of $notInQuery'); } + let additionalOptions = { + redirectClassNameForKey: notInQueryValue.redirectClassNameForKey + }; + var subquery = new RestQuery( this.config, this.auth, notInQueryValue.className, - notInQueryValue.where); + notInQueryValue.where, additionalOptions); return subquery.execute().then((response) => { var values = []; for (var result of response.results) { values.push({ __type: 'Pointer', - className: notInQueryValue.className, + className: subquery.className, objectId: result.objectId }); } @@ -385,7 +391,6 @@ RestQuery.prototype.runFind = function() { r.className = this.redirectClassName; } } - this.response = {results: results}; }); }; @@ -423,7 +428,7 @@ RestQuery.prototype.handleInclude = function() { this.include = this.include.slice(1); return this.handleInclude(); } - + return pathResponse; }; From 3451fc3430bc65f6e73d80358ac9c55fd87491e1 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Tue, 15 Mar 2016 19:13:40 -0400 Subject: [PATCH 3/3] fixes same bug affecting $select and $dontSelect --- spec/ParseRelation.spec.js | 83 +++++++++++++++++++++++++++++++++++++- src/RestQuery.js | 12 +++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index 434e919229..fa409f2f45 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -550,7 +550,6 @@ describe('Parse.Relation testing', () => { }); return Promise.resolve(); }).then(() => { - console.log(''); // Query on the relation of another owner let object = new Parse.Object('AnotherOwner'); object.id = anotherOwner.id; @@ -571,4 +570,86 @@ describe('Parse.Relation testing', () => { done(); }) }); + + it("select query", function(done) { + var RestaurantObject = Parse.Object.extend("Restaurant"); + var PersonObject = Parse.Object.extend("Person"); + var OwnerObject = Parse.Object.extend('Owner'); + var restaurants = [ + new RestaurantObject({ ratings: 5, location: "Djibouti" }), + new RestaurantObject({ ratings: 3, location: "Ouagadougou" }), + ]; + let persons = [ + new PersonObject({ name: "Bob", hometown: "Djibouti" }), + new PersonObject({ name: "Tom", hometown: "Ouagadougou" }), + new PersonObject({ name: "Billy", hometown: "Detroit" }), + ]; + let owner = new OwnerObject({name: 'Joe'}); + let ownerId; + let allObjects = [owner].concat(restaurants).concat(persons); + expect(allObjects.length).toEqual(6); + Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() { + ownerId = owner.id; + owner.relation('restaurants').add(restaurants); + return owner.save() + }).then(() => { + let unfetchedOwner = new OwnerObject(); + unfetchedOwner.id = owner.id; + var query = unfetchedOwner.relation('restaurants').query(); + query.greaterThan("ratings", 4); + var mainQuery = new Parse.Query(PersonObject); + mainQuery.matchesKeyInQuery("hometown", "location", query); + mainQuery.find(expectSuccess({ + success: function(results) { + equal(results.length, 1); + if (results.length > 0) { + equal(results[0].get('name'), 'Bob'); + } + done(); + } + })); + }); + }); + + it("dontSelect query", function(done) { + var RestaurantObject = Parse.Object.extend("Restaurant"); + var PersonObject = Parse.Object.extend("Person"); + var OwnerObject = Parse.Object.extend('Owner'); + var restaurants = [ + new RestaurantObject({ ratings: 5, location: "Djibouti" }), + new RestaurantObject({ ratings: 3, location: "Ouagadougou" }), + ]; + let persons = [ + new PersonObject({ name: "Bob", hometown: "Djibouti" }), + new PersonObject({ name: "Tom", hometown: "Ouagadougou" }), + new PersonObject({ name: "Billy", hometown: "Detroit" }), + ]; + let owner = new OwnerObject({name: 'Joe'}); + let ownerId; + let allObjects = [owner].concat(restaurants).concat(persons); + expect(allObjects.length).toEqual(6); + Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() { + ownerId = owner.id; + owner.relation('restaurants').add(restaurants); + return owner.save() + }).then(() => { + let unfetchedOwner = new OwnerObject(); + unfetchedOwner.id = owner.id; + var query = unfetchedOwner.relation('restaurants').query(); + query.greaterThan("ratings", 4); + var mainQuery = new Parse.Query(PersonObject); + mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); + mainQuery.ascending('name'); + mainQuery.find(expectSuccess({ + success: function(results) { + equal(results.length, 2); + if (results.length > 0) { + equal(results[0].get('name'), 'Billy'); + equal(results[1].get('name'), 'Tom'); + } + done(); + } + })); + }); + }); }); diff --git a/src/RestQuery.js b/src/RestQuery.js index 4c5bb0b736..530a7b8980 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -299,9 +299,13 @@ RestQuery.prototype.replaceSelect = function() { 'improper usage of $select'); } + let additionalOptions = { + redirectClassNameForKey: selectValue.query.redirectClassNameForKey + }; + var subquery = new RestQuery( this.config, this.auth, selectValue.query.className, - selectValue.query.where); + selectValue.query.where, additionalOptions); return subquery.execute().then((response) => { var values = []; for (var result of response.results) { @@ -340,9 +344,13 @@ RestQuery.prototype.replaceDontSelect = function() { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $dontSelect'); } + let additionalOptions = { + redirectClassNameForKey: dontSelectValue.query.redirectClassNameForKey + }; + var subquery = new RestQuery( this.config, this.auth, dontSelectValue.query.className, - dontSelectValue.query.where); + dontSelectValue.query.where, additionalOptions); return subquery.execute().then((response) => { var values = []; for (var result of response.results) {