fix(database): update belongs to many relation with target collection (#2393)
* fix(database): update belongs to many relation with target collection * chore: test
This commit is contained in:
parent
457082ffa1
commit
e3e4e63146
@ -2,6 +2,89 @@ import { Collection } from '@nocobase/database';
|
|||||||
import Database from '../../database';
|
import Database from '../../database';
|
||||||
import { BelongsToManyRepository } from '../../relation-repository/belongs-to-many-repository';
|
import { BelongsToManyRepository } from '../../relation-repository/belongs-to-many-repository';
|
||||||
import { mockDatabase } from '../index';
|
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<BelongsToManyRepository>('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', () => {
|
describe('belongs to many with collection that has no id key', () => {
|
||||||
let db: Database;
|
let db: Database;
|
||||||
|
@ -121,14 +121,14 @@ export const DialectVersionAccessors = {
|
|||||||
if (v.toLowerCase().includes('mariadb')) {
|
if (v.toLowerCase().includes('mariadb')) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const m = /([\d+\.]+)/.exec(v);
|
const m = /([\d+.]+)/.exec(v);
|
||||||
return m[0];
|
return m[0];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
postgres: {
|
postgres: {
|
||||||
sql: 'select version() as version',
|
sql: 'select version() as version',
|
||||||
get: (v: string) => {
|
get: (v: string) => {
|
||||||
const m = /([\d+\.]+)/.exec(v);
|
const m = /([\d+.]+)/.exec(v);
|
||||||
return semver.minVersion(m[0]).version;
|
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();
|
this.initListener();
|
||||||
patchSequelizeQueryInterface(this);
|
patchSequelizeQueryInterface(this);
|
||||||
}
|
}
|
||||||
@ -711,7 +700,7 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
|||||||
|
|
||||||
async auth(options: Omit<QueryOptions, 'retry'> & { retry?: number | Pick<QueryOptions, 'retry'> } = {}) {
|
async auth(options: Omit<QueryOptions, 'retry'> & { retry?: number | Pick<QueryOptions, 'retry'> } = {}) {
|
||||||
const { retry = 10, ...others } = options;
|
const { retry = 10, ...others } = options;
|
||||||
const delay = (ms) => new Promise((yea) => setTimeout(yea, ms));
|
const delay = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
|
||||||
let count = 1;
|
let count = 1;
|
||||||
const authenticate = async () => {
|
const authenticate = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { HasOne, MultiAssociationAccessors, Sequelize, Transaction, Transactionable } from 'sequelize';
|
import { HasOne, MultiAssociationAccessors, Sequelize, Transaction, Transactionable } from 'sequelize';
|
||||||
|
import lodash from 'lodash';
|
||||||
import injectTargetCollection from '../decorators/target-collection-decorator';
|
import injectTargetCollection from '../decorators/target-collection-decorator';
|
||||||
import {
|
import {
|
||||||
CommonFindOptions,
|
CommonFindOptions,
|
||||||
@ -134,10 +135,8 @@ export abstract class MultipleRelationRepository extends RelationRepository {
|
|||||||
|
|
||||||
const values = guard.sanitize(options.values);
|
const values = guard.sanitize(options.values);
|
||||||
|
|
||||||
const queryOptions = this.buildQueryOptions(options as any);
|
|
||||||
|
|
||||||
const instances = await this.find({
|
const instances = await this.find({
|
||||||
...queryOptions,
|
...(lodash.omit(options, ['values']) as any),
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user