[postgres] Improve performance when adding many new fields to the Schema (#3740)
This commit is contained in:
committed by
Florent Vilmart
parent
5e14147676
commit
69042fbf50
@@ -181,7 +181,7 @@ describe('SchemaController', () => {
|
||||
it('can add classes without needing an object', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'String'}
|
||||
foo: {type: 'String'},
|
||||
}))
|
||||
.then(actualSchema => {
|
||||
const expectedSchema = {
|
||||
@@ -210,6 +210,81 @@ describe('SchemaController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('can update classes without needing an object', done => {
|
||||
const levelPermissions = {
|
||||
find: { '*': true },
|
||||
get: { '*': true },
|
||||
create: { '*': true },
|
||||
update: { '*': true },
|
||||
delete: { '*': true },
|
||||
addField: { '*': true },
|
||||
};
|
||||
config.database.loadSchema()
|
||||
.then(schema => {
|
||||
schema.validateObject('NewClass', { foo: 2 })
|
||||
.then(() => schema.reloadData())
|
||||
.then(() => schema.updateClass('NewClass', {
|
||||
fooOne: {type: 'Number'},
|
||||
fooTwo: {type: 'Array'},
|
||||
fooThree: {type: 'Date'},
|
||||
fooFour: {type: 'Object'},
|
||||
fooFive: {type: 'Relation', targetClass: '_User' },
|
||||
fooSix: {type: 'String'},
|
||||
fooSeven: {type: 'Object' },
|
||||
fooEight: {type: 'String'},
|
||||
fooNine: {type: 'String'},
|
||||
fooTeen: {type: 'Number' },
|
||||
fooEleven: {type: 'String'},
|
||||
fooTwelve: {type: 'String'},
|
||||
fooThirteen: {type: 'String'},
|
||||
fooFourteen: {type: 'String'},
|
||||
fooFifteen: {type: 'String'},
|
||||
fooSixteen: {type: 'String'},
|
||||
fooEighteen: {type: 'String'},
|
||||
fooNineteen: {type: 'String'},
|
||||
}, levelPermissions, config.database))
|
||||
.then(actualSchema => {
|
||||
const expectedSchema = {
|
||||
className: 'NewClass',
|
||||
fields: {
|
||||
objectId: { type: 'String' },
|
||||
updatedAt: { type: 'Date' },
|
||||
createdAt: { type: 'Date' },
|
||||
ACL: { type: 'ACL' },
|
||||
foo: { type: 'Number' },
|
||||
fooOne: {type: 'Number'},
|
||||
fooTwo: {type: 'Array'},
|
||||
fooThree: {type: 'Date'},
|
||||
fooFour: {type: 'Object'},
|
||||
fooFive: {type: 'Relation', targetClass: '_User' },
|
||||
fooSix: {type: 'String'},
|
||||
fooSeven: {type: 'Object' },
|
||||
fooEight: {type: 'String'},
|
||||
fooNine: {type: 'String'},
|
||||
fooTeen: {type: 'Number' },
|
||||
fooEleven: {type: 'String'},
|
||||
fooTwelve: {type: 'String'},
|
||||
fooThirteen: {type: 'String'},
|
||||
fooFourteen: {type: 'String'},
|
||||
fooFifteen: {type: 'String'},
|
||||
fooSixteen: {type: 'String'},
|
||||
fooEighteen: {type: 'String'},
|
||||
fooNineteen: {type: 'String'},
|
||||
},
|
||||
classLevelPermissions: { ...levelPermissions },
|
||||
};
|
||||
|
||||
expect(dd(actualSchema, expectedSchema)).toEqual(undefined);
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
console.trace(error);
|
||||
done();
|
||||
fail('Error creating class: ' + JSON.stringify(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('will fail to create a class if that class was already created by an object', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => {
|
||||
|
||||
@@ -543,15 +543,15 @@ export class PostgresStorageAdapter {
|
||||
promise = t.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`})
|
||||
}
|
||||
return promise.then(() => {
|
||||
return t.any('SELECT "schema" FROM "_SCHEMA" WHERE "className" = $<className>', {className});
|
||||
return t.any('SELECT "schema" FROM "_SCHEMA" WHERE "className" = $<className> and ("schema"::json->\'fields\'->$<fieldName>) is not null', {className, fieldName});
|
||||
}).then(result => {
|
||||
if (fieldName in result[0].schema.fields) {
|
||||
if (result[0]) {
|
||||
throw "Attempted to add a field that already exists";
|
||||
} else {
|
||||
result[0].schema.fields[fieldName] = type;
|
||||
const path = `{fields,${fieldName}}`;
|
||||
return t.none(
|
||||
'UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>',
|
||||
{schema: result[0].schema, className}
|
||||
'UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $<path>, $<type>) WHERE "className"=$<className>',
|
||||
{ path, type, className }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user