Skip to content

Commit 752f0e9

Browse files
authored
Fixes #3195 (#3201)
* Adds error reproduction * Fix transform in order to accept nested array results in $in/$nin The error originated by the nesting of 2 array in $in [["..."]], using _.flatMap with those will guarantee at the lower level that the query is properly resolved * nits * _.flatMap the $in/$nin values
1 parent 025e7a3 commit 752f0e9

File tree

3 files changed

+52
-15
lines changed

3 files changed

+52
-15
lines changed

spec/ParseQuery.spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,6 +2467,35 @@ describe('Parse.Query testing', () => {
24672467
});
24682468
});
24692469

2470+
it("should match a key in an array (#3195)", function(done) {
2471+
var AuthorObject = Parse.Object.extend("Author");
2472+
var GroupObject = Parse.Object.extend("Group");
2473+
var PostObject = Parse.Object.extend("Post");
2474+
2475+
return new AuthorObject().save().then((user) => {
2476+
const post = new PostObject({
2477+
author: user
2478+
});
2479+
2480+
const group = new GroupObject({
2481+
members: [user],
2482+
});
2483+
2484+
return Parse.Promise.when(post.save(), group.save());
2485+
}).then((p) => {
2486+
return new Parse.Query(PostObject)
2487+
.matchesKeyInQuery("author", "members", new Parse.Query(GroupObject))
2488+
.find()
2489+
.then((r) => {
2490+
expect(r.length).toEqual(1);
2491+
if (r.length > 0) {
2492+
expect(r[0].id).toEqual(p.id);
2493+
}
2494+
done();
2495+
}, done.fail);
2496+
});
2497+
});
2498+
24702499
it('should find objects with array of pointers', (done) => {
24712500
var objects = [];
24722501
while(objects.length != 5) {

src/Adapters/Storage/Mongo/MongoTransform.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,9 @@ function transformQueryKeyValue(className, key, value, schema) {
223223
}
224224

225225
// Handle query constraints
226-
if (transformConstraint(value, expectedTypeIsArray) !== CannotTransform) {
227-
return {key, value: transformConstraint(value, expectedTypeIsArray)};
226+
const transformedConstraint = transformConstraint(value, expectedTypeIsArray);
227+
if (transformedConstraint !== CannotTransform) {
228+
return {key, value: transformedConstraint};
228229
}
229230

230231
if (expectedTypeIsArray && !(value instanceof Array)) {
@@ -508,7 +509,14 @@ function transformConstraint(constraint, inArray) {
508509
if (typeof constraint !== 'object' || !constraint) {
509510
return CannotTransform;
510511
}
511-
512+
const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom;
513+
const transformer = (atom) => {
514+
const result = transformFunction(atom);
515+
if (result === CannotTransform) {
516+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${JSON.stringify(atom)}`);
517+
}
518+
return result;
519+
}
512520
// keys is the constraints in reverse alphabetical order.
513521
// This is a hack so that:
514522
// $regex is handled before $options
@@ -524,10 +532,7 @@ function transformConstraint(constraint, inArray) {
524532
case '$exists':
525533
case '$ne':
526534
case '$eq':
527-
answer[key] = inArray ? transformInteriorAtom(constraint[key]) : transformTopLevelAtom(constraint[key]);
528-
if (answer[key] === CannotTransform) {
529-
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${constraint[key]}`);
530-
}
535+
answer[key] = transformer(constraint[key]);
531536
break;
532537

533538
case '$in':
@@ -536,12 +541,14 @@ function transformConstraint(constraint, inArray) {
536541
if (!(arr instanceof Array)) {
537542
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
538543
}
539-
answer[key] = arr.map(value => {
540-
const result = inArray ? transformInteriorAtom(value) : transformTopLevelAtom(value);
541-
if (result === CannotTransform) {
542-
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${value}`);
543-
}
544-
return result;
544+
answer[key] = _.flatMap(arr, value => {
545+
return ((atom) => {
546+
if (Array.isArray(atom)) {
547+
return value.map(transformer);
548+
} else {
549+
return transformer(atom);
550+
}
551+
})(value);
545552
});
546553
break;
547554
}

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createClient } from './PostgresClient';
22
import Parse from 'parse/node';
3+
import _ from 'lodash';
34

45
const PostgresRelationDoesNotExistError = '42P01';
56
const PostgresDuplicateRelationError = '42P07';
@@ -296,10 +297,10 @@ const buildWhereClause = ({ schema, query, index }) => {
296297
}
297298
}
298299
if (fieldValue.$in) {
299-
createConstraint(fieldValue.$in, false);
300+
createConstraint(_.flatMap(fieldValue.$in, elt => elt), false);
300301
}
301302
if (fieldValue.$nin) {
302-
createConstraint(fieldValue.$nin, true);
303+
createConstraint(_.flatMap(fieldValue.$nin, elt => elt), true);
303304
}
304305
}
305306

0 commit comments

Comments
 (0)