Add Indexes to Schema API (#4240)

* Add Indexes to Schema API

* error handling

* ci errors

* postgres support

* full text compound indexes

* pg clean up

* get indexes on startup

* test compound index on startup

* add default _id to index, full Text index on startup

* lint

* fix test
This commit is contained in:
Diamond Lewis
2017-11-25 13:55:34 -06:00
committed by Florent Vilmart
parent 6a1510729a
commit 4bccf96ae7
10 changed files with 965 additions and 83 deletions

View File

@@ -287,18 +287,28 @@ const convertAdapterSchemaToParseSchema = ({...schema}) => {
schema.fields.password = { type: 'String' };
}
if (schema.indexes && Object.keys(schema.indexes).length === 0) {
delete schema.indexes;
}
return schema;
}
const injectDefaultSchema = ({className, fields, classLevelPermissions}) => ({
className,
fields: {
...defaultColumns._Default,
...(defaultColumns[className] || {}),
...fields,
},
classLevelPermissions,
});
const injectDefaultSchema = ({className, fields, classLevelPermissions, indexes}) => {
const defaultSchema = {
className,
fields: {
...defaultColumns._Default,
...(defaultColumns[className] || {}),
...fields,
},
classLevelPermissions,
};
if (indexes && Object.keys(indexes).length !== 0) {
defaultSchema.indexes = indexes;
}
return defaultSchema;
};
const _HooksSchema = {className: "_Hooks", fields: defaultColumns._Hooks};
const _GlobalConfigSchema = { className: "_GlobalConfig", fields: defaultColumns._GlobalConfig }
@@ -344,6 +354,7 @@ export default class SchemaController {
_dbAdapter;
data;
perms;
indexes;
constructor(databaseAdapter, schemaCache) {
this._dbAdapter = databaseAdapter;
@@ -352,6 +363,8 @@ export default class SchemaController {
this.data = {};
// this.perms[className][operation] tells you the acl-style permissions
this.perms = {};
// this.indexes[className][operation] tells you the indexes
this.indexes = {};
}
reloadData(options = {clearCache: false}) {
@@ -370,9 +383,11 @@ export default class SchemaController {
.then(allSchemas => {
const data = {};
const perms = {};
const indexes = {};
allSchemas.forEach(schema => {
data[schema.className] = injectDefaultSchema(schema).fields;
perms[schema.className] = schema.classLevelPermissions;
indexes[schema.className] = schema.indexes;
});
// Inject the in-memory classes
@@ -380,13 +395,16 @@ export default class SchemaController {
const schema = injectDefaultSchema({ className });
data[className] = schema.fields;
perms[className] = schema.classLevelPermissions;
indexes[className] = schema.indexes;
});
this.data = data;
this.perms = perms;
this.indexes = indexes;
delete this.reloadDataPromise;
}, (err) => {
this.data = {};
this.perms = {};
this.indexes = {};
delete this.reloadDataPromise;
throw err;
});
@@ -424,7 +442,8 @@ export default class SchemaController {
return Promise.resolve({
className,
fields: this.data[className],
classLevelPermissions: this.perms[className]
classLevelPermissions: this.perms[className],
indexes: this.indexes[className]
});
}
return this._cache.getOneSchema(className).then((cached) => {
@@ -449,13 +468,13 @@ export default class SchemaController {
// on success, and rejects with an error on fail. Ensure you
// have authorization (master key, or client class creation
// enabled) before calling this function.
addClassIfNotExists(className, fields = {}, classLevelPermissions) {
addClassIfNotExists(className, fields = {}, classLevelPermissions, indexes = {}) {
var validationError = this.validateNewClass(className, fields, classLevelPermissions);
if (validationError) {
return Promise.reject(validationError);
}
return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ fields, classLevelPermissions, className }))
return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ fields, classLevelPermissions, indexes, className }))
.then(convertAdapterSchemaToParseSchema)
.then((res) => {
return this._cache.clear().then(() => {
@@ -471,7 +490,7 @@ export default class SchemaController {
});
}
updateClass(className, submittedFields, classLevelPermissions, database) {
updateClass(className, submittedFields, classLevelPermissions, indexes, database) {
return this.getOneSchema(className)
.then(schema => {
const existingFields = schema.fields;
@@ -509,7 +528,6 @@ export default class SchemaController {
if (deletedFields.length > 0) {
deletePromise = this.deleteFields(deletedFields, className, database);
}
return deletePromise // Delete Everything
.then(() => this.reloadData({ clearCache: true })) // Reload our Schema, so we have all the new values
.then(() => {
@@ -520,12 +538,20 @@ export default class SchemaController {
return Promise.all(promises);
})
.then(() => this.setPermissions(className, classLevelPermissions, newSchema))
.then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, newSchema))
.then(() => this.reloadData({ clearCache: true }))
//TODO: Move this logic into the database adapter
.then(() => ({
className: className,
fields: this.data[className],
classLevelPermissions: this.perms[className]
}));
.then(() => {
const reloadedSchema = {
className: className,
fields: this.data[className],
classLevelPermissions: this.perms[className],
};
if (this.indexes[className] && Object.keys(this.indexes[className]).length !== 0) {
reloadedSchema.indexes = this.indexes[className];
}
return reloadedSchema;
});
})
.catch(error => {
if (error === undefined) {
@@ -620,8 +646,7 @@ export default class SchemaController {
return Promise.resolve();
}
validateCLP(perms, newSchema);
return this._dbAdapter.setClassLevelPermissions(className, perms)
.then(() => this.reloadData({ clearCache: true }));
return this._dbAdapter.setClassLevelPermissions(className, perms);
}
// Returns a promise that resolves successfully to the new schema