From 6d996b60951c40727f526550f3b2085d9386cf8a Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 29 Sep 2022 10:44:18 +1000 Subject: [PATCH 1/3] fix: orQuery does not work with relations --- spec/ParseRelation.spec.js | 47 +++++++++++++++++++++++++++ src/Controllers/DatabaseController.js | 9 +++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index b6e94e1a02..16ddf973ba 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -410,6 +410,53 @@ 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 query4 = new Parse.Query('ChildObject'); + // query4.equalTo('toChilds', childObjects[2]); + // await query4.find(); + + 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..dac2e67ec1 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -926,12 +926,12 @@ class DatabaseController { // Modifies query so that it no longer has $in on relation fields, or // equal-to-pointer constraints on relation fields. // Returns a promise that resolves when query is mutated - reduceInRelation(className: string, query: any, schema: any): Promise { + async 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 if (query['$or']) { const ors = query['$or']; - return Promise.all( + await Promise.all( ors.map((aQuery, index) => { return this.reduceInRelation(className, aQuery, schema).then(aQuery => { query['$or'][index] = aQuery; @@ -943,7 +943,7 @@ class DatabaseController { } if (query['$and']) { const ands = query['$and']; - return Promise.all( + await Promise.all( ands.map((aQuery, index) => { return this.reduceInRelation(className, aQuery, schema).then(aQuery => { query['$and'][index] = aQuery; @@ -955,6 +955,9 @@ class DatabaseController { } const promises = 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); From 73e1de694ba04c37faaca61eb1c16d1958379d2c Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 29 Sep 2022 10:46:32 +1000 Subject: [PATCH 2/3] Update ParseRelation.spec.js --- spec/ParseRelation.spec.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index 16ddf973ba..f0c746065d 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -446,10 +446,6 @@ describe('Parse.Relation testing', () => { const query = Parse.Query.or(query1, query2); query.equalTo('toChilds', childObjects[2]); - // const query4 = new Parse.Query('ChildObject'); - // query4.equalTo('toChilds', childObjects[2]); - // await query4.find(); - const list = await query.find(); const objectIds = list.map(item => item.id); expect(objectIds.indexOf(parent.id)).not.toBe(-1); From 63167d38babd8a7c93116521d1df40f9faca9c73 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 29 Sep 2022 10:51:08 +1000 Subject: [PATCH 3/3] Update DatabaseController.js --- src/Controllers/DatabaseController.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index dac2e67ec1..7a8cce1479 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -926,35 +926,32 @@ class DatabaseController { // Modifies query so that it no longer has $in on relation fields, or // equal-to-pointer constraints on relation fields. // Returns a promise that resolves when query is mutated - async reduceInRelation(className: string, query: any, schema: any): Promise { + 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']; - await 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']; - await 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; } @@ -1019,7 +1016,7 @@ class DatabaseController { }); }); - return Promise.all(promises).then(() => { + return Promise.all([...promises, ...otherKeys]).then(() => { return Promise.resolve(query); }); }