From ad62422859a1bf0be84882b684084dd1a58452a8 Mon Sep 17 00:00:00 2001 From: dblythy Date: Tue, 27 Jun 2023 17:25:00 +1000 Subject: [PATCH 1/3] feat: allow creating of unique indexes --- spec/schemas.spec.js | 100 ++++++++++++++++++ .../Storage/Mongo/MongoStorageAdapter.js | 16 ++- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 9557dd7924..a4d6d24346 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -3051,6 +3051,42 @@ describe('schemas', () => { }); }); + it('allows add unique index when you create a class', async () => { + await reconfigureServer({ silent: false }); + const response = await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClass', + fields: { + aString: { type: 'String' }, + }, + indexes: { + name1: { aString: 1, _options: { unique: true } }, + }, + }, + }); + expect(response.data).toEqual({ + className: 'NewClass', + fields: { + ACL: { type: 'ACL' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + objectId: { type: 'String' }, + aString: { type: 'String' }, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + name1: { aString: 1, _options: { unique: true } }, + }, + }); + const indexes = await config.database.adapter.getIndexes('NewClass'); + expect(indexes.length).toBe(2); + expect(indexes.filter(row => row.unique).length).toEqual(1); + }); + it('empty index returns nothing', done => { request({ url: 'http://localhost:8378/1/schemas', @@ -3148,6 +3184,70 @@ describe('schemas', () => { }); }); + it('lets you add unique indexes', async () => { + await request({ + url: 'http://localhost:8378/1/schemas/NewClass', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: {}, + }); + let response = await request({ + url: 'http://localhost:8378/1/schemas/NewClass', + method: 'PUT', + headers: masterKeyHeaders, + json: true, + body: { + fields: { + aString: { type: 'String' }, + }, + indexes: { + name1: { aString: 1, _options: { unique: true } }, + }, + }, + }); + expect( + dd(response.data, { + className: 'NewClass', + fields: { + ACL: { type: 'ACL' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + objectId: { type: 'String' }, + aString: { type: 'String' }, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1, _options: { unique: true } }, + }, + }) + ).toEqual(undefined); + response = await request({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + }); + expect(response.data).toEqual({ + className: 'NewClass', + fields: { + ACL: { type: 'ACL' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + objectId: { type: 'String' }, + aString: { type: 'String' }, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1, _options: { unique: true } }, + }, + }); + const indexes = await config.database.adapter.getIndexes('NewClass'); + expect(indexes.length).toEqual(2); + expect(indexes.filter(row => row.unique).length).toEqual(1); + }); + it_only_db('mongo')('lets you add index with with pointer like structure', done => { request({ url: 'http://localhost:8378/1/schemas/NewClass', diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 2f59819895..237cf1f661 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -2,6 +2,7 @@ import MongoCollection from './MongoCollection'; import MongoSchemaCollection from './MongoSchemaCollection'; import { StorageAdapter } from '../StorageAdapter'; +import deepcopy from 'deepcopy'; import type { SchemaType, QueryType, StorageClass, QueryOptions } from '../StorageAdapter'; import { parse as parseUrl, format as formatUrl } from '../../../vendor/mongodbUrl'; import { @@ -275,7 +276,13 @@ export class MongoStorageAdapter implements StorageAdapter { const deletePromises = []; const insertedIndexes = []; Object.keys(submittedIndexes).forEach(name => { - const field = submittedIndexes[name]; + const field = deepcopy(submittedIndexes[name]); + let indexOptions = {}; + if (field._options) { + indexOptions = field._options; + delete field._options; + } + console.log(existingIndexes[name], field); if (existingIndexes[name] && field.__op !== 'Delete') { throw new Parse.Error(Parse.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); } @@ -303,11 +310,16 @@ export class MongoStorageAdapter implements StorageAdapter { ); } }); - existingIndexes[name] = field; insertedIndexes.push({ key: field, name, + ...indexOptions, }); + const fieldCopy = deepcopy(field); + if (indexOptions) { + fieldCopy._options = indexOptions; + } + existingIndexes[name] = fieldCopy; } }); let insertPromise = Promise.resolve(); From 29c98785c3ca354ef1aa02982e57be9a37577c26 Mon Sep 17 00:00:00 2001 From: dblythy Date: Tue, 27 Jun 2023 17:26:43 +1000 Subject: [PATCH 2/3] Update MongoStorageAdapter.js --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 237cf1f661..745ea488f4 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -282,7 +282,6 @@ export class MongoStorageAdapter implements StorageAdapter { indexOptions = field._options; delete field._options; } - console.log(existingIndexes[name], field); if (existingIndexes[name] && field.__op !== 'Delete') { throw new Parse.Error(Parse.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); } From a561edd26e9604798fe275af5cf8355daa7d7998 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 28 Jun 2023 12:27:39 +1000 Subject: [PATCH 3/3] Update MongoStorageAdapter.js --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 745ea488f4..7ed34b0645 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -315,7 +315,7 @@ export class MongoStorageAdapter implements StorageAdapter { ...indexOptions, }); const fieldCopy = deepcopy(field); - if (indexOptions) { + if (Object.keys(indexOptions).length) { fieldCopy._options = indexOptions; } existingIndexes[name] = fieldCopy;