[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 => {
|
it('can add classes without needing an object', done => {
|
||||||
config.database.loadSchema()
|
config.database.loadSchema()
|
||||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||||
foo: {type: 'String'}
|
foo: {type: 'String'},
|
||||||
}))
|
}))
|
||||||
.then(actualSchema => {
|
.then(actualSchema => {
|
||||||
const expectedSchema = {
|
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 => {
|
it('will fail to create a class if that class was already created by an object', done => {
|
||||||
config.database.loadSchema()
|
config.database.loadSchema()
|
||||||
.then(schema => {
|
.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}`})
|
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 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 => {
|
}).then(result => {
|
||||||
if (fieldName in result[0].schema.fields) {
|
if (result[0]) {
|
||||||
throw "Attempted to add a field that already exists";
|
throw "Attempted to add a field that already exists";
|
||||||
} else {
|
} else {
|
||||||
result[0].schema.fields[fieldName] = type;
|
const path = `{fields,${fieldName}}`;
|
||||||
return t.none(
|
return t.none(
|
||||||
'UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>',
|
'UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $<path>, $<type>) WHERE "className"=$<className>',
|
||||||
{schema: result[0].schema, className}
|
{ path, type, className }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user