Skip to content

Commit 0708af1

Browse files
committed
Move "No two geopoints" logic into mongo adapter (#1491)
* Move "No two geopoints" logic into mongo adapter * Semicolon
1 parent cecb2a1 commit 0708af1

File tree

4 files changed

+51
-39
lines changed

4 files changed

+51
-39
lines changed

spec/ParseGeoPoint.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ describe('Parse.GeoPoint testing', () => {
8585
equal(results.length, 3);
8686
done();
8787
}, (err) => {
88-
console.log(err);
89-
fail();
88+
fail("Couldn't query GeoPoint");
89+
fail(err)
9090
});
9191
});
9292

src/Adapters/Storage/Mongo/MongoSchemaCollection.js

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,45 @@ class MongoSchemaCollection {
179179
return this._collection.upsertOne(_mongoSchemaQueryFromNameQuery(name, query), update);
180180
}
181181

182-
updateField(className: string, fieldName: string, type: string) {
183-
// We don't have this field. Update the schema.
184-
// Note that we use the $exists guard and $set to avoid race
185-
// conditions in the database. This is important!
186-
let query = {};
187-
query[fieldName] = { '$exists': false };
188-
let update = {};
189-
if (typeof type === 'string') {
190-
type = {
191-
type: type
182+
// Add a field to the schema. If database does not support the field
183+
// type (e.g. mongo doesn't support more than one GeoPoint in a class) reject with an "Incorrect Type"
184+
// Parse error with a desciptive message. If the field already exists, this function must
185+
// not modify the schema, and must reject with an error. Exact error format is TBD. If this function
186+
// is called for a class that doesn't exist, this function must create that class.
187+
188+
// TODO: throw an error if an unsupported field type is passed. Deciding whether a type is supported
189+
// should be the job of the adapter. Some adapters may not support GeoPoint at all. Others may
190+
// Support additional types that Mongo doesn't, like Money, or something.
191+
192+
// TODO: don't spend an extra query on finding the schema if the type we are trying to add isn't a GeoPoint.
193+
addFieldIfNotExists(className: string, fieldName: string, type: string) {
194+
return this.findSchema(className)
195+
.then(schema => {
196+
// The schema exists. Check for existing GeoPoints.
197+
if (type.type === 'GeoPoint') {
198+
// Make sure there are not other geopoint fields
199+
if (Object.keys(schema.fields).some(existingField => schema.fields[existingField].type === 'GeoPoint')) {
200+
return Promise.reject(new Parse.Error(Parse.Error.INCORRECT_TYPE, 'MongoDB only supports one GeoPoint field in a class.'));
201+
}
192202
}
193-
}
194-
update[fieldName] = parseFieldTypeToMongoFieldType(type);
195-
update = {'$set': update};
196-
return this.upsertSchema(className, query, update);
203+
return Promise.resolve();
204+
}, error => {
205+
// If error is undefined, the schema doesn't exist, and we can create the schema with the field.
206+
// If some other error, reject with it.
207+
if (error === undefined) {
208+
return Promise.resolve();
209+
}
210+
throw Promise.reject(error);
211+
})
212+
.then(() => {
213+
// We use $exists and $set to avoid overwriting the field type if it
214+
// already exists. (it could have added inbetween the last query and the update)
215+
return this.upsertSchema(
216+
className,
217+
{ [fieldName]: { '$exists': false } },
218+
{ '$set' : { [fieldName]: parseFieldTypeToMongoFieldType(type) } }
219+
);
220+
});
197221
}
198222

199223
get transform() {

src/Adapters/Storage/Mongo/MongoTransform.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -346,23 +346,20 @@ function CannotTransform() {}
346346
// Raises an error if this cannot possibly be valid REST format.
347347
// Returns CannotTransform if it's just not an atom, or if force is
348348
// true, throws an error.
349-
function transformAtom(atom, force, options) {
350-
options = options || {};
351-
var inArray = options.inArray;
352-
var inObject = options.inObject;
349+
function transformAtom(atom, force, {
350+
inArray,
351+
inObject,
352+
} = {}) {
353353
switch(typeof atom) {
354354
case 'string':
355355
case 'number':
356356
case 'boolean':
357357
return atom;
358-
359358
case 'undefined':
360359
return atom;
361360
case 'symbol':
362361
case 'function':
363-
throw new Parse.Error(Parse.Error.INVALID_JSON,
364-
'cannot transform value: ' + atom);
365-
362+
throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`);
366363
case 'object':
367364
if (atom instanceof Date) {
368365
// Technically dates are not rest format, but, it seems pretty
@@ -377,7 +374,7 @@ function transformAtom(atom, force, options) {
377374
// TODO: check validity harder for the __type-defined types
378375
if (atom.__type == 'Pointer') {
379376
if (!inArray && !inObject) {
380-
return atom.className + '$' + atom.objectId;
377+
return `${atom.className}$${atom.objectId}`;
381378
}
382379
return {
383380
__type: 'Pointer',
@@ -402,15 +399,13 @@ function transformAtom(atom, force, options) {
402399
}
403400

404401
if (force) {
405-
throw new Parse.Error(Parse.Error.INVALID_JSON,
406-
'bad atom: ' + atom);
402+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${atom}`);
407403
}
408404
return CannotTransform;
409405

410406
default:
411407
// I don't think typeof can ever let us get here
412-
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR,
413-
'really did not expect value: ' + atom);
408+
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, `really did not expect value: ${atom}`);
414409
}
415410
}
416411

src/Schema.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -479,18 +479,11 @@ class SchemaController {
479479
return Promise.resolve(this);
480480
}
481481

482-
if (type === 'GeoPoint') {
483-
// Make sure there are not other geopoint fields
484-
for (let otherKey in this.data[className]) {
485-
if (this.data[className][otherKey].type === 'GeoPoint') {
486-
throw new Parse.Error(
487-
Parse.Error.INCORRECT_TYPE,
488-
'there can only be one geopoint field in a class');
489-
}
490-
}
482+
if (typeof type === 'string') {
483+
type = { type };
491484
}
492485

493-
return this._collection.updateField(className, fieldName, type).then(() => {
486+
return this._collection.addFieldIfNotExists(className, fieldName, type).then(() => {
494487
// The update succeeded. Reload the schema
495488
return this.reloadData();
496489
}, () => {

0 commit comments

Comments
 (0)