New query condition support to match all strings that starts with some other given strings (#3864)

* feat: Convert $regex value to RegExp object

* feat: Add lib folder

* Revert "feat: Add lib folder"

This reverts commit c9dfbcbf699ff220baeb2df5586a944d19808e5e.

* feat: Add $regex test in $all array

* test: Test regex with $all only in MongoDB

* Revert "test: Test regex with $all only in MongoDB"

This reverts commit d7194c7869dee98d924fbc2502593a198385dba1.

* feat: Add tests for containsAllStartingWith

* feat: Add postgres support

Thanks to @dplewis

* feat: Check that all values in $all must be regex or none

* test: Check that $all vaules must be regex or none

* feat: Update tests to use only REST API

* refactor: Move $all regex check to adapter

* feat: Check for valid $all values in progres

* refactor: Update function name

* fix:  Postgres $all values regex checking

* fix: Check starts with as string

* fix: Define contains all regex sql function

* fix: Wrong value check

* fix: Check valid data

* fix: Check regex when there is only one value

* fix: Constains all starting with string returns empty with bad params

* fix: Pass correct regex value

* feat: Add missing tests

* feat: Add missing tests

* feat: Add more tests

* fix: Unify MongoDB and PostgreSQL functionality

* fix: Lint checks

* fix: Test broken

$regex in $all list must be { $regex: "string" }

* test for empty $all
This commit is contained in:
Eduard Bosch Bertran
2018-05-16 03:42:32 +02:00
committed by Diamond Lewis
parent 2c357df33e
commit c0e3672e32
7 changed files with 395 additions and 2 deletions

View File

@@ -418,7 +418,20 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
}
if (Array.isArray(fieldValue.$all) && isArrayField) {
patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`);
if (isAnyValueRegexStartsWith(fieldValue.$all)) {
if (!isAllValuesRegexOrNone(fieldValue.$all)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'All $all values must be of regex type or none: '
+ fieldValue.$all);
}
for (let i = 0; i < fieldValue.$all.length; i += 1) {
const value = processRegexPattern(fieldValue.$all[i].$regex);
fieldValue.$all[i] = value.substring(1) + '%';
}
patterns.push(`array_contains_all_regex($${index}:name, $${index + 1}::jsonb)`);
} else {
patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`);
}
values.push(fieldName, JSON.stringify(fieldValue.$all));
index += 2;
}
@@ -1758,6 +1771,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
t.none(sql.array.addUnique),
t.none(sql.array.remove),
t.none(sql.array.containsAll),
t.none(sql.array.containsAllRegex),
t.none(sql.array.contains)
]);
});
@@ -1862,6 +1876,40 @@ function processRegexPattern(s) {
return literalizeRegexPart(s);
}
function isStartsWithRegex(value) {
if (!value || typeof value !== 'string' || !value.startsWith('^')) {
return false;
}
const matches = value.match(/\^\\Q.*\\E/);
return !!matches;
}
function isAllValuesRegexOrNone(values) {
if (!values || !Array.isArray(values) || values.length === 0) {
return true;
}
const firstValuesIsRegex = isStartsWithRegex(values[0].$regex);
if (values.length === 1) {
return firstValuesIsRegex;
}
for (let i = 1, length = values.length; i < length; ++i) {
if (firstValuesIsRegex !== isStartsWithRegex(values[i].$regex)) {
return false;
}
}
return true;
}
function isAnyValueRegexStartsWith(values) {
return values.some(function (value) {
return isStartsWithRegex(value.$regex);
});
}
function createLiteralRegex(remaining) {
return remaining.split('').map(c => {
if (c.match(/[0-9a-zA-Z]/) !== null) {