Skip to content

Commit ec45ba0

Browse files
fix: actual fix
1 parent d4da486 commit ec45ba0

File tree

1 file changed

+47
-44
lines changed

1 file changed

+47
-44
lines changed

src/Adapters/Storage/Mongo/MongoTransform.js

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ function transformQueryKeyValue(className, key, value, schema, count = false) {
327327
}
328328

329329
// Handle query constraints
330-
const transformedConstraint = transformConstraint(value, field, count);
330+
const transformedConstraint = transformConstraint(value, field, key, count);
331331
if (transformedConstraint !== CannotTransform) {
332332
if (transformedConstraint.$text) {
333333
return { key: '$text', value: transformedConstraint.$text };
@@ -651,12 +651,15 @@ function transformTopLevelAtom(atom, field) {
651651
// If it is not a valid constraint but it could be a valid something
652652
// else, return CannotTransform.
653653
// inArray is whether this is an array field.
654-
function transformConstraint(constraint, field, count = false) {
654+
function transformConstraint(constraint, field, key, count = false) {
655655
const inArray = field && field.type && field.type === 'Array';
656+
// Check wether the given key has `.`
657+
const isNestedKey = key.indexOf('.') > -1;
656658
if (typeof constraint !== 'object' || !constraint) {
657659
return CannotTransform;
658660
}
659-
const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom;
661+
// For inArray or nested key, we need to transform the interior atom
662+
const transformFunction = (inArray || isNestedKey) ? transformInteriorAtom : transformTopLevelAtom;
660663
const transformer = atom => {
661664
const result = transformFunction(atom, field);
662665
if (result === CannotTransform) {
@@ -668,18 +671,18 @@ function transformConstraint(constraint, field, count = false) {
668671
// This is a hack so that:
669672
// $regex is handled before $options
670673
// $nearSphere is handled before $maxDistance
671-
var keys = Object.keys(constraint).sort().reverse();
674+
var constraintKeys = Object.keys(constraint).sort().reverse();
672675
var answer = {};
673-
for (var key of keys) {
674-
switch (key) {
676+
for (var constraintKey of constraintKeys) {
677+
switch (constraintKey) {
675678
case '$lt':
676679
case '$lte':
677680
case '$gt':
678681
case '$gte':
679682
case '$exists':
680683
case '$ne':
681684
case '$eq': {
682-
const val = constraint[key];
685+
const val = constraint[constraintKey];
683686
if (val && typeof val === 'object' && val.$relativeTime) {
684687
if (field && field.type !== 'Date') {
685688
throw new Parse.Error(
@@ -688,7 +691,7 @@ function transformConstraint(constraint, field, count = false) {
688691
);
689692
}
690693

691-
switch (key) {
694+
switch (constraintKey) {
692695
case '$exists':
693696
case '$ne':
694697
case '$eq':
@@ -700,28 +703,28 @@ function transformConstraint(constraint, field, count = false) {
700703

701704
const parserResult = Utils.relativeTimeToDate(val.$relativeTime);
702705
if (parserResult.status === 'success') {
703-
answer[key] = parserResult.result;
706+
answer[constraintKey] = parserResult.result;
704707
break;
705708
}
706709

707710
log.info('Error while parsing relative date', parserResult);
708711
throw new Parse.Error(
709712
Parse.Error.INVALID_JSON,
710-
`bad $relativeTime (${key}) value. ${parserResult.info}`
713+
`bad $relativeTime (${constraintKey}) value. ${parserResult.info}`
711714
);
712715
}
713716

714-
answer[key] = transformer(val);
717+
answer[constraintKey] = transformer(val);
715718
break;
716719
}
717720

718721
case '$in':
719722
case '$nin': {
720-
const arr = constraint[key];
723+
const arr = constraint[constraintKey];
721724
if (!(arr instanceof Array)) {
722-
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
725+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + constraintKey + ' value');
723726
}
724-
answer[key] = _.flatMap(arr, value => {
727+
answer[constraintKey] = _.flatMap(arr, value => {
725728
return (atom => {
726729
if (Array.isArray(atom)) {
727730
return value.map(transformer);
@@ -733,13 +736,13 @@ function transformConstraint(constraint, field, count = false) {
733736
break;
734737
}
735738
case '$all': {
736-
const arr = constraint[key];
739+
const arr = constraint[constraintKey];
737740
if (!(arr instanceof Array)) {
738-
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
741+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + constraintKey + ' value');
739742
}
740-
answer[key] = arr.map(transformInteriorAtom);
743+
answer[constraintKey] = arr.map(transformInteriorAtom);
741744

742-
const values = answer[key];
745+
const values = answer[constraintKey];
743746
if (isAnyValueRegex(values) && !isAllValuesRegexOrNone(values)) {
744747
throw new Parse.Error(
745748
Parse.Error.INVALID_JSON,
@@ -750,15 +753,15 @@ function transformConstraint(constraint, field, count = false) {
750753
break;
751754
}
752755
case '$regex':
753-
var s = constraint[key];
756+
var s = constraint[constraintKey];
754757
if (typeof s !== 'string') {
755758
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad regex: ' + s);
756759
}
757-
answer[key] = s;
760+
answer[constraintKey] = s;
758761
break;
759762

760763
case '$containedBy': {
761-
const arr = constraint[key];
764+
const arr = constraint[constraintKey];
762765
if (!(arr instanceof Array)) {
763766
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $containedBy: should be an array`);
764767
}
@@ -768,87 +771,87 @@ function transformConstraint(constraint, field, count = false) {
768771
break;
769772
}
770773
case '$options':
771-
answer[key] = constraint[key];
774+
answer[constraintKey] = constraint[constraintKey];
772775
break;
773776

774777
case '$text': {
775-
const search = constraint[key].$search;
778+
const search = constraint[constraintKey].$search;
776779
if (typeof search !== 'object') {
777780
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $search, should be object`);
778781
}
779782
if (!search.$term || typeof search.$term !== 'string') {
780783
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $term, should be string`);
781784
} else {
782-
answer[key] = {
785+
answer[constraintKey] = {
783786
$search: search.$term,
784787
};
785788
}
786789
if (search.$language && typeof search.$language !== 'string') {
787790
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $language, should be string`);
788791
} else if (search.$language) {
789-
answer[key].$language = search.$language;
792+
answer[constraintKey].$language = search.$language;
790793
}
791794
if (search.$caseSensitive && typeof search.$caseSensitive !== 'boolean') {
792795
throw new Parse.Error(
793796
Parse.Error.INVALID_JSON,
794797
`bad $text: $caseSensitive, should be boolean`
795798
);
796799
} else if (search.$caseSensitive) {
797-
answer[key].$caseSensitive = search.$caseSensitive;
800+
answer[constraintKey].$caseSensitive = search.$caseSensitive;
798801
}
799802
if (search.$diacriticSensitive && typeof search.$diacriticSensitive !== 'boolean') {
800803
throw new Parse.Error(
801804
Parse.Error.INVALID_JSON,
802805
`bad $text: $diacriticSensitive, should be boolean`
803806
);
804807
} else if (search.$diacriticSensitive) {
805-
answer[key].$diacriticSensitive = search.$diacriticSensitive;
808+
answer[constraintKey].$diacriticSensitive = search.$diacriticSensitive;
806809
}
807810
break;
808811
}
809812
case '$nearSphere': {
810-
const point = constraint[key];
813+
const point = constraint[constraintKey];
811814
if (count) {
812815
answer.$geoWithin = {
813816
$centerSphere: [[point.longitude, point.latitude], constraint.$maxDistance],
814817
};
815818
} else {
816-
answer[key] = [point.longitude, point.latitude];
819+
answer[constraintKey] = [point.longitude, point.latitude];
817820
}
818821
break;
819822
}
820823
case '$maxDistance': {
821824
if (count) {
822825
break;
823826
}
824-
answer[key] = constraint[key];
827+
answer[constraintKey] = constraint[constraintKey];
825828
break;
826829
}
827830
// The SDKs don't seem to use these but they are documented in the
828831
// REST API docs.
829832
case '$maxDistanceInRadians':
830-
answer['$maxDistance'] = constraint[key];
833+
answer['$maxDistance'] = constraint[constraintKey];
831834
break;
832835
case '$maxDistanceInMiles':
833-
answer['$maxDistance'] = constraint[key] / 3959;
836+
answer['$maxDistance'] = constraint[constraintKey] / 3959;
834837
break;
835838
case '$maxDistanceInKilometers':
836-
answer['$maxDistance'] = constraint[key] / 6371;
839+
answer['$maxDistance'] = constraint[constraintKey] / 6371;
837840
break;
838841

839842
case '$select':
840843
case '$dontSelect':
841844
throw new Parse.Error(
842845
Parse.Error.COMMAND_UNAVAILABLE,
843-
'the ' + key + ' constraint is not supported yet'
846+
'the ' + constraintKey + ' constraint is not supported yet'
844847
);
845848

846849
case '$within':
847-
var box = constraint[key]['$box'];
850+
var box = constraint[constraintKey]['$box'];
848851
if (!box || box.length != 2) {
849852
throw new Parse.Error(Parse.Error.INVALID_JSON, 'malformatted $within arg');
850853
}
851-
answer[key] = {
854+
answer[constraintKey] = {
852855
$box: [
853856
[box[0].longitude, box[0].latitude],
854857
[box[1].longitude, box[1].latitude],
@@ -857,8 +860,8 @@ function transformConstraint(constraint, field, count = false) {
857860
break;
858861

859862
case '$geoWithin': {
860-
const polygon = constraint[key]['$polygon'];
861-
const centerSphere = constraint[key]['$centerSphere'];
863+
const polygon = constraint[constraintKey]['$polygon'];
864+
const centerSphere = constraint[constraintKey]['$centerSphere'];
862865
if (polygon !== undefined) {
863866
let points;
864867
if (typeof polygon === 'object' && polygon.__type === 'Polygon') {
@@ -895,7 +898,7 @@ function transformConstraint(constraint, field, count = false) {
895898
}
896899
return [point.longitude, point.latitude];
897900
});
898-
answer[key] = {
901+
answer[constraintKey] = {
899902
$polygon: points,
900903
};
901904
} else if (centerSphere !== undefined) {
@@ -924,14 +927,14 @@ function transformConstraint(constraint, field, count = false) {
924927
'bad $geoWithin value; $centerSphere distance invalid'
925928
);
926929
}
927-
answer[key] = {
930+
answer[constraintKey] = {
928931
$centerSphere: [[point.longitude, point.latitude], distance],
929932
};
930933
}
931934
break;
932935
}
933936
case '$geoIntersects': {
934-
const point = constraint[key]['$point'];
937+
const point = constraint[constraintKey]['$point'];
935938
if (!GeoPointCoder.isValidJSON(point)) {
936939
throw new Parse.Error(
937940
Parse.Error.INVALID_JSON,
@@ -940,7 +943,7 @@ function transformConstraint(constraint, field, count = false) {
940943
} else {
941944
Parse.GeoPoint._validate(point.latitude, point.longitude);
942945
}
943-
answer[key] = {
946+
answer[constraintKey] = {
944947
$geometry: {
945948
type: 'Point',
946949
coordinates: [point.longitude, point.latitude],
@@ -949,8 +952,8 @@ function transformConstraint(constraint, field, count = false) {
949952
break;
950953
}
951954
default:
952-
if (key.match(/^\$+/)) {
953-
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad constraint: ' + key);
955+
if (constraintKey.match(/^\$+/)) {
956+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad constraint: ' + constraintKey);
954957
}
955958
return CannotTransform;
956959
}

0 commit comments

Comments
 (0)