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) {
|
it("dontSelect query", function(done) {
|
||||||
const RestaurantObject = Parse.Object.extend("Restaurant");
|
const RestaurantObject = Parse.Object.extend("Restaurant");
|
||||||
const PersonObject = Parse.Object.extend("Person");
|
const PersonObject = Parse.Object.extend("Person");
|
||||||
|
|||||||
@@ -247,9 +247,9 @@ function transformQueryKeyValue(className, key, value, schema) {
|
|||||||
case '_perishable_token':
|
case '_perishable_token':
|
||||||
case '_email_verify_token': return {key, value}
|
case '_email_verify_token': return {key, value}
|
||||||
case '$or':
|
case '$or':
|
||||||
return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))};
|
|
||||||
case '$and':
|
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':
|
case 'lastUsed':
|
||||||
if (valueAsDate(value)) {
|
if (valueAsDate(value)) {
|
||||||
return {key: '_last_used', value: 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}`);
|
patterns.push(`$${index}:name = $${index + 1}`);
|
||||||
values.push(fieldName, fieldValue);
|
values.push(fieldName, fieldValue);
|
||||||
index += 2;
|
index += 2;
|
||||||
} else if (fieldName === '$or' || fieldName === '$and') {
|
} else if (['$or', '$nor', '$and'].includes(fieldName)) {
|
||||||
const clauses = [];
|
const clauses = [];
|
||||||
const clauseValues = [];
|
const clauseValues = [];
|
||||||
fieldValue.forEach((subQuery) => {
|
fieldValue.forEach((subQuery) => {
|
||||||
@@ -317,8 +317,11 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
|
|||||||
index += clause.values.length;
|
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);
|
values.push(...clauseValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const transformObjectACL = ({ ACL, ...result }) => {
|
|||||||
return 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 => {
|
const isSpecialQueryKey = key => {
|
||||||
return specialQuerykeys.indexOf(key) >= 0;
|
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 => {
|
Object.keys(query).forEach(key => {
|
||||||
if (query && query[key] && query[key].$regex) {
|
if (query && query[key] && query[key].$regex) {
|
||||||
if (typeof query[key].$options === 'string') {
|
if (typeof query[key].$options === 'string') {
|
||||||
|
|||||||
Reference in New Issue
Block a user