From e3e4e63146451d9c1c9cadc977374f3fd35c078b Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Fri, 4 Aug 2023 18:19:45 +0800 Subject: [PATCH] fix(database): update belongs to many relation with target collection (#2393) * fix(database): update belongs to many relation with target collection * chore: test --- .../belongs-to-many-repository.test.ts | 83 +++++++++++++++++++ packages/core/database/src/database.ts | 17 +--- .../multiple-relation-repository.ts | 5 +- 3 files changed, 88 insertions(+), 17 deletions(-) diff --git a/packages/core/database/src/__tests__/relation-repository/belongs-to-many-repository.test.ts b/packages/core/database/src/__tests__/relation-repository/belongs-to-many-repository.test.ts index b674fd740..b1cfb3c98 100644 --- a/packages/core/database/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +++ b/packages/core/database/src/__tests__/relation-repository/belongs-to-many-repository.test.ts @@ -2,6 +2,89 @@ import { Collection } from '@nocobase/database'; import Database from '../../database'; import { BelongsToManyRepository } from '../../relation-repository/belongs-to-many-repository'; import { mockDatabase } from '../index'; +import { pgOnly } from '@nocobase/test'; + +pgOnly()('belongs to many with targetCollection', () => { + let db: Database; + + let Org: Collection; + let User: Collection; + let Student: Collection; + + let OrgUser: Collection; + + beforeEach(async () => { + db = mockDatabase(); + + await db.clean({ drop: true }); + + OrgUser = db.collection({ + name: 'org_user', + }); + + Org = db.collection({ + name: 'orgs', + fields: [ + { type: 'string', name: 'name' }, + { type: 'belongsToMany', name: 'users', target: 'users', through: 'org_user' }, + ], + }); + + User = db.collection({ + name: 'users', + fields: [ + { type: 'string', name: 'name' }, + { type: 'belongsToMany', name: 'orgs', target: 'orgs', through: 'org_user' }, + ], + }); + + Student = db.collection({ + name: 'students', + inherits: ['users'], + fields: [{ type: 'integer', name: 'score' }], + }); + + await db.sync(); + }); + + afterEach(async () => { + await db.close(); + }); + + it('should update child collection', async () => { + const u1 = await User.repository.create({ + values: { + name: 'user1', + }, + }); + + const s1 = await Student.repository.create({ + values: { + name: 'student1', + score: 100, + }, + }); + + const org1 = await Org.repository.create({ + values: { + name: 'org1', + users: [u1.get('id'), s1.get('id')], + }, + }); + + const repository = Org.repository.relation('users').of(org1.get('id')); + await repository.update({ + filterByTk: s1.get('id'), + targetCollection: Student.name, + values: { + score: 200, + }, + }); + + const s1AfterUpdate = await Student.repository.findOne({}); + expect(s1AfterUpdate.get('score')).toBe(200); + }); +}); describe('belongs to many with collection that has no id key', () => { let db: Database; diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 64b9afdaf..7440c2c16 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -121,14 +121,14 @@ export const DialectVersionAccessors = { if (v.toLowerCase().includes('mariadb')) { return ''; } - const m = /([\d+\.]+)/.exec(v); + const m = /([\d+.]+)/.exec(v); return m[0]; }, }, postgres: { sql: 'select version() as version', get: (v: string) => { - const m = /([\d+\.]+)/.exec(v); + const m = /([\d+.]+)/.exec(v); return semver.minVersion(m[0]).version; }, }, @@ -290,17 +290,6 @@ export class Database extends EventEmitter implements AsyncEmitter { }), }); - this.migrator = new Umzug({ - logger: migratorOptions.logger || console, - migrations: this.migrations.callback(), - context, - storage: new SequelizeStorage({ - modelName: `${this.options.tablePrefix || ''}migrations`, - ...migratorOptions.storage, - sequelize: this.sequelize, - }), - }); - this.initListener(); patchSequelizeQueryInterface(this); } @@ -711,7 +700,7 @@ export class Database extends EventEmitter implements AsyncEmitter { async auth(options: Omit & { retry?: number | Pick } = {}) { const { retry = 10, ...others } = options; - const delay = (ms) => new Promise((yea) => setTimeout(yea, ms)); + const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); let count = 1; const authenticate = async () => { try { diff --git a/packages/core/database/src/relation-repository/multiple-relation-repository.ts b/packages/core/database/src/relation-repository/multiple-relation-repository.ts index f254f2eb2..4e598c31f 100644 --- a/packages/core/database/src/relation-repository/multiple-relation-repository.ts +++ b/packages/core/database/src/relation-repository/multiple-relation-repository.ts @@ -1,4 +1,5 @@ import { HasOne, MultiAssociationAccessors, Sequelize, Transaction, Transactionable } from 'sequelize'; +import lodash from 'lodash'; import injectTargetCollection from '../decorators/target-collection-decorator'; import { CommonFindOptions, @@ -134,10 +135,8 @@ export abstract class MultipleRelationRepository extends RelationRepository { const values = guard.sanitize(options.values); - const queryOptions = this.buildQueryOptions(options as any); - const instances = await this.find({ - ...queryOptions, + ...(lodash.omit(options, ['values']) as any), transaction, });