Adding $nor operator support (#4768)
* adding nor to specialQuerykeys * adding nor suport * adding test * CRLF * adding postgres NOR * adding nor validation * adding NOR test * adding test amd fixing NOR cases * revert the nor logic
This commit is contained in:
committed by
Diamond Lewis
parent
a9ebc2b9af
commit
77ed10f57b
@@ -2567,6 +2567,63 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('$nor valid query', (done) => {
|
||||
const objects = Array.from(Array(10).keys()).map((rating) => {
|
||||
return new TestObject({ 'rating': rating });
|
||||
});
|
||||
|
||||
const highValue = 5;
|
||||
const lowValue = 3;
|
||||
const options = Object.assign({}, masterKeyOptions, {
|
||||
body: {
|
||||
where: {
|
||||
$nor: [
|
||||
{ rating : { $gt : highValue } },
|
||||
{ rating : { $lte : lowValue } },
|
||||
]
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
Parse.Object.saveAll(objects).then(() => {
|
||||
return rp.get(Parse.serverURL + "/classes/TestObject", options);
|
||||
}).then((results) => {
|
||||
expect(results.results.length).toBe(highValue - lowValue);
|
||||
expect(results.results.every(res => res.rating > lowValue && res.rating <= highValue)).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('$nor invalid query - empty array', (done) => {
|
||||
const options = Object.assign({}, masterKeyOptions, {
|
||||
body: {
|
||||
where: { $nor: [] },
|
||||
}
|
||||
});
|
||||
const obj = new TestObject();
|
||||
obj.save().then(() => {
|
||||
return rp.get(Parse.serverURL + "/classes/TestObject", options);
|
||||
}).then(done.fail).catch((error) => {
|
||||
equal(error.error.code, Parse.Error.INVALID_QUERY);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('$nor invalid query - wrong type', (done) => {
|
||||
const options = Object.assign({}, masterKeyOptions, {
|
||||
body: {
|
||||
where: { $nor: 1337 },
|
||||
}
|
||||
});
|
||||
const obj = new TestObject();
|
||||
obj.save().then(() => {
|
||||
return rp.get(Parse.serverURL + "/classes/TestObject", options);
|
||||
}).then(done.fail).catch((error) => {
|
||||
equal(error.error.code, Parse.Error.INVALID_QUERY);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("dontSelect query", function(done) {
|
||||
const RestaurantObject = Parse.Object.extend("Restaurant");
|
||||
const PersonObject = Parse.Object.extend("Person");
|
||||
|
||||
@@ -247,9 +247,9 @@ function transformQueryKeyValue(className, key, value, schema) {
|
||||
case '_perishable_token':
|
||||
case '_email_verify_token': return {key, value}
|
||||
case '$or':
|
||||
return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))};
|
||||
case '$and':
|
||||
return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema))};
|
||||
case '$nor':
|
||||
return {key: key, value: value.map(subQuery => transformWhere(className, subQuery, schema))};
|
||||
case 'lastUsed':
|
||||
if (valueAsDate(value)) {
|
||||
return {key: '_last_used', value: valueAsDate(value)}
|
||||
|
||||
@@ -306,7 +306,7 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
|
||||
patterns.push(`$${index}:name = $${index + 1}`);
|
||||
values.push(fieldName, fieldValue);
|
||||
index += 2;
|
||||
} else if (fieldName === '$or' || fieldName === '$and') {
|
||||
} else if (['$or', '$nor', '$and'].includes(fieldName)) {
|
||||
const clauses = [];
|
||||
const clauseValues = [];
|
||||
fieldValue.forEach((subQuery) => {
|
||||
@@ -317,8 +317,11 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
|
||||
index += clause.values.length;
|
||||
}
|
||||
});
|
||||
const orOrAnd = fieldName === '$or' ? ' OR ' : ' AND ';
|
||||
patterns.push(`(${clauses.join(orOrAnd)})`);
|
||||
|
||||
const orOrAnd = fieldName === '$and' ? ' AND ' : ' OR ';
|
||||
const not = fieldName === '$nor' ? ' NOT ' : '';
|
||||
|
||||
patterns.push(`${not}(${clauses.join(orOrAnd)})`);
|
||||
values.push(...clauseValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ const transformObjectACL = ({ ACL, ...result }) => {
|
||||
return result;
|
||||
}
|
||||
|
||||
const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count'];
|
||||
const specialQuerykeys = ['$and', '$or', '$nor', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count'];
|
||||
|
||||
const isSpecialQueryKey = key => {
|
||||
return specialQuerykeys.indexOf(key) >= 0;
|
||||
@@ -111,6 +111,14 @@ const validateQuery = (query: any): void => {
|
||||
}
|
||||
}
|
||||
|
||||
if (query.$nor) {
|
||||
if (query.$nor instanceof Array && query.$nor.length > 0) {
|
||||
query.$nor.forEach(validateQuery);
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Bad $nor format - use an array of at least 1 value.');
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(query).forEach(key => {
|
||||
if (query && query[key] && query[key].$regex) {
|
||||
if (typeof query[key].$options === 'string') {
|
||||
|
||||
Reference in New Issue
Block a user