[postgres] Improve performance when adding many new fields to the Schema (#3740)

This commit is contained in:
Paulo Vítor S Reis
2017-04-23 18:25:33 -03:00
committed by Florent Vilmart
parent 5e14147676
commit 69042fbf50
2 changed files with 81 additions and 6 deletions

View File

@@ -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 => {

View File

@@ -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 }
);
}
});