From 24fb25754f57e200ca3139c7629b0b004f4c8248 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Sun, 19 Feb 2023 11:55:25 +0800 Subject: [PATCH] fix: column not exists error after destory relation field (#1465) * test: field not exists * fix: create association field after other association field destroyed --- packages/core/database/src/collection.ts | 18 +- .../__tests__/collections.repository.test.ts | 168 ++++++++++++++++++ .../hooks/afterCreateForForeignKeyField.ts | 2 + 3 files changed, 182 insertions(+), 6 deletions(-) diff --git a/packages/core/database/src/collection.ts b/packages/core/database/src/collection.ts index c4898c506..b1a3cc3f6 100644 --- a/packages/core/database/src/collection.ts +++ b/packages/core/database/src/collection.ts @@ -488,12 +488,18 @@ export class Collection< // @ts-ignore this.model._indexes = lodash.uniqBy( - indexes.map((item) => { - if (this.options.underscored) { - item.fields = item.fields.map((field) => snakeCase(field)); - } - return item; - }), + indexes + .filter((item) => { + return item.fields.every((field) => + Object.values(this.model.rawAttributes).find((fieldVal) => fieldVal.field === field), + ); + }) + .map((item) => { + if (this.options.underscored) { + item.fields = item.fields.map((field) => snakeCase(field)); + } + return item; + }), 'name', ); } diff --git a/packages/plugins/collection-manager/src/__tests__/collections.repository.test.ts b/packages/plugins/collection-manager/src/__tests__/collections.repository.test.ts index 13309e424..68954c8d8 100644 --- a/packages/plugins/collection-manager/src/__tests__/collections.repository.test.ts +++ b/packages/plugins/collection-manager/src/__tests__/collections.repository.test.ts @@ -343,4 +343,172 @@ describe('collections repository', () => { const tableInfo4 = await getTableInfo(); expect(tableInfo4['test_field']).not.toBeDefined(); }); + + it('should destroy relation field after foreignKey destroyed', async () => { + await Collection.repository.create({ + context: {}, + values: { + name: 'c1Z', + fields: [ + { + type: 'string', + name: 'a', + }, + ], + }, + }); + + await Collection.repository.create({ + context: {}, + values: { + name: 'c2Z', + }, + }); + + await Field.repository.create({ + values: { + name: 'g1', + foreignKey: 'a', + target: 'c2Z', + type: 'belongsTo', + collectionName: 'c1Z', + interface: 'm2o', + }, + context: {}, + }); + + const foreignKey = await Field.repository.findOne({ + filter: { + collectionName: 'c1Z', + name: 'a', + }, + }); + + expect(foreignKey.get('isForeignKey')).toBeTruthy(); + + await Field.repository.destroy({ + filter: { + name: 'a', + }, + context: {}, + }); + + expect(await Field.repository.findOne({ filter: { name: 'g1' } })).toBeFalsy(); + }); + + it('should create field normal when repeat create and destroy', async () => { + const c1Z = await Collection.repository.create({ + values: { + name: 'c1Z', + }, + context: {}, + }); + + const c2Z = await Collection.repository.create({ + values: { + name: 'c2Z', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'a', + type: 'string', + collectionName: 'c1Z', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'b', + type: 'integer', + collectionName: 'c1Z', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'g1', + type: 'belongsTo', + target: 'c2Z', + foreignKey: 'a', + collectionName: 'c1Z', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'g2', + type: 'belongsTo', + target: 'c2Z', + foreignKey: 'b', + collectionName: 'c1Z', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'g3', + type: 'belongsTo', + target: 'c2Z', + foreignKey: 'a', + collectionName: 'c1Z', + interface: 'm2o', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'g1', + type: 'hasMany', + target: 'c1Z', + foreignKey: 'a', + collectionName: 'c2Z', + interface: 'o2m', + }, + context: {}, + }); + + await Field.repository.create({ + values: { + name: 'g2', + type: 'hasMany', + target: 'c1Z', + foreignKey: 'b', + collectionName: 'c2Z', + interface: 'o2m', + }, + context: {}, + }); + + await Field.repository.destroy({ + filter: { + collectionName: 'c1Z', + name: ['a', 'b'], + }, + context: {}, + }); + + expect(await Field.repository.count()).toBe(0); + + await Field.repository.create({ + values: { + name: 'g5', + type: 'belongsTo', + target: 'c2Z', + foreignKey: 'a1', + collectionName: 'c1Z', + interface: 'm2o', + }, + context: {}, + }); + + expect(await Field.repository.count()).toBe(2); + }); }); diff --git a/packages/plugins/collection-manager/src/hooks/afterCreateForForeignKeyField.ts b/packages/plugins/collection-manager/src/hooks/afterCreateForForeignKeyField.ts index 07972363d..f1688d872 100644 --- a/packages/plugins/collection-manager/src/hooks/afterCreateForForeignKeyField.ts +++ b/packages/plugins/collection-manager/src/hooks/afterCreateForForeignKeyField.ts @@ -11,9 +11,11 @@ export function afterCreateForForeignKeyField(db: Database) { const M = collection.model; const attr = M.rawAttributes[foreignKey]; + if (!attr) { throw new Error(`${collectionName}.${foreignKey} does not exists`); } + return attribute2field(attr); }