* 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
This commit is contained in:
Florent Vilmart
2016-12-07 20:03:40 -05:00
committed by GitHub
parent 025e7a3218
commit 752f0e9143
3 changed files with 52 additions and 15 deletions

View File

@@ -2467,6 +2467,35 @@ describe('Parse.Query testing', () => {
});
});
it("should match a key in an array (#3195)", function(done) {
var AuthorObject = Parse.Object.extend("Author");
var GroupObject = Parse.Object.extend("Group");
var PostObject = Parse.Object.extend("Post");
return new AuthorObject().save().then((user) => {
const post = new PostObject({
author: user
});
const group = new GroupObject({
members: [user],
});
return Parse.Promise.when(post.save(), group.save());
}).then((p) => {
return new Parse.Query(PostObject)
.matchesKeyInQuery("author", "members", new Parse.Query(GroupObject))
.find()
.then((r) => {
expect(r.length).toEqual(1);
if (r.length > 0) {
expect(r[0].id).toEqual(p.id);
}
done();
}, done.fail);
});
});
it('should find objects with array of pointers', (done) => {
var objects = [];
while(objects.length != 5) {

View File

@@ -223,8 +223,9 @@ function transformQueryKeyValue(className, key, value, schema) {
}
// Handle query constraints
if (transformConstraint(value, expectedTypeIsArray) !== CannotTransform) {
return {key, value: transformConstraint(value, expectedTypeIsArray)};
const transformedConstraint = transformConstraint(value, expectedTypeIsArray);
if (transformedConstraint !== CannotTransform) {
return {key, value: transformedConstraint};
}
if (expectedTypeIsArray && !(value instanceof Array)) {
@@ -508,7 +509,14 @@ function transformConstraint(constraint, inArray) {
if (typeof constraint !== 'object' || !constraint) {
return CannotTransform;
}
const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom;
const transformer = (atom) => {
const result = transformFunction(atom);
if (result === CannotTransform) {
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${JSON.stringify(atom)}`);
}
return result;
}
// keys is the constraints in reverse alphabetical order.
// This is a hack so that:
// $regex is handled before $options
@@ -524,10 +532,7 @@ function transformConstraint(constraint, inArray) {
case '$exists':
case '$ne':
case '$eq':
answer[key] = inArray ? transformInteriorAtom(constraint[key]) : transformTopLevelAtom(constraint[key]);
if (answer[key] === CannotTransform) {
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${constraint[key]}`);
}
answer[key] = transformer(constraint[key]);
break;
case '$in':
@@ -536,12 +541,14 @@ function transformConstraint(constraint, inArray) {
if (!(arr instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
}
answer[key] = arr.map(value => {
const result = inArray ? transformInteriorAtom(value) : transformTopLevelAtom(value);
if (result === CannotTransform) {
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${value}`);
}
return result;
answer[key] = _.flatMap(arr, value => {
return ((atom) => {
if (Array.isArray(atom)) {
return value.map(transformer);
} else {
return transformer(atom);
}
})(value);
});
break;
}

View File

@@ -1,5 +1,6 @@
import { createClient } from './PostgresClient';
import Parse from 'parse/node';
import _ from 'lodash';
const PostgresRelationDoesNotExistError = '42P01';
const PostgresDuplicateRelationError = '42P07';
@@ -296,10 +297,10 @@ const buildWhereClause = ({ schema, query, index }) => {
}
}
if (fieldValue.$in) {
createConstraint(fieldValue.$in, false);
createConstraint(_.flatMap(fieldValue.$in, elt => elt), false);
}
if (fieldValue.$nin) {
createConstraint(fieldValue.$nin, true);
createConstraint(_.flatMap(fieldValue.$nin, elt => elt), true);
}
}