From 28f0d2667787d2ac68726607b811d6f0ef62b9f1 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 24 Oct 2022 21:45:17 +1100 Subject: [PATCH] fix: relation constraints in compound queries `Parse.Query.or`, `Parse.Query.and` not working (#8203) --- spec/ParseRelation.spec.js | 43 +++++++++++++++++++++++++++ src/Controllers/DatabaseController.js | 24 +++++++-------- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index b6e94e1a02..f0c746065d 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -410,6 +410,49 @@ describe('Parse.Relation testing', () => { }); }); + it('or queries with base constraint on relation field', async () => { + const ChildObject = Parse.Object.extend('ChildObject'); + const childObjects = []; + for (let i = 0; i < 10; i++) { + childObjects.push(new ChildObject({ x: i })); + } + await Parse.Object.saveAll(childObjects); + const ParentObject = Parse.Object.extend('ParentObject'); + const parent = new ParentObject(); + parent.set('x', 4); + const relation = parent.relation('toChilds'); + relation.add(childObjects[0]); + relation.add(childObjects[1]); + relation.add(childObjects[2]); + + const parent2 = new ParentObject(); + parent2.set('x', 3); + const relation2 = parent2.relation('toChilds'); + relation2.add(childObjects[0]); + relation2.add(childObjects[1]); + relation2.add(childObjects[2]); + + const parents = []; + parents.push(parent); + parents.push(parent2); + parents.push(new ParentObject()); + + await Parse.Object.saveAll(parents); + const query1 = new Parse.Query(ParentObject); + query1.equalTo('x', 4); + const query2 = new Parse.Query(ParentObject); + query2.equalTo('x', 3); + + const query = Parse.Query.or(query1, query2); + query.equalTo('toChilds', childObjects[2]); + + const list = await query.find(); + const objectIds = list.map(item => item.id); + expect(objectIds.indexOf(parent.id)).not.toBe(-1); + expect(objectIds.indexOf(parent2.id)).not.toBe(-1); + equal(list.length, 2, 'There should be 2 results'); + }); + it('Get query on relation using un-fetched parent object', done => { // Setup data model const Wheel = Parse.Object.extend('Wheel'); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 7dbd789c3b..7a8cce1479 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -929,32 +929,32 @@ class DatabaseController { reduceInRelation(className: string, query: any, schema: any): Promise { // Search for an in-relation or equal-to-relation // Make it sequential for now, not sure of paralleization side effects + const promises = []; if (query['$or']) { const ors = query['$or']; - return Promise.all( - ors.map((aQuery, index) => { + promises.push( + ...ors.map((aQuery, index) => { return this.reduceInRelation(className, aQuery, schema).then(aQuery => { query['$or'][index] = aQuery; }); }) - ).then(() => { - return Promise.resolve(query); - }); + ); } if (query['$and']) { const ands = query['$and']; - return Promise.all( - ands.map((aQuery, index) => { + promises.push( + ...ands.map((aQuery, index) => { return this.reduceInRelation(className, aQuery, schema).then(aQuery => { query['$and'][index] = aQuery; }); }) - ).then(() => { - return Promise.resolve(query); - }); + ); } - const promises = Object.keys(query).map(key => { + const otherKeys = Object.keys(query).map(key => { + if (key === '$and' || key === '$or') { + return; + } const t = schema.getExpectedType(className, key); if (!t || t.type !== 'Relation') { return Promise.resolve(query); @@ -1016,7 +1016,7 @@ class DatabaseController { }); }); - return Promise.all(promises).then(() => { + return Promise.all([...promises, ...otherKeys]).then(() => { return Promise.resolve(query); }); }