fix: destroy through table record referencing collections table (#1611)
* test: destory through table record referencing collections table * fix: belongs to many fields to reference
This commit is contained in:
parent
708675deb9
commit
e566d56c2d
@ -1,5 +1,3 @@
|
|||||||
import lodash from 'lodash';
|
|
||||||
|
|
||||||
export interface Reference {
|
export interface Reference {
|
||||||
sourceCollectionName: string;
|
sourceCollectionName: string;
|
||||||
sourceField: string;
|
sourceField: string;
|
||||||
@ -16,6 +14,8 @@ class ReferencesMap {
|
|||||||
reference.onDelete = 'SET NULL';
|
reference.onDelete = 'SET NULL';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reference.onDelete = reference.onDelete.toUpperCase();
|
||||||
|
|
||||||
const existReference = this.existReference(reference);
|
const existReference = this.existReference(reference);
|
||||||
|
|
||||||
if (existReference && existReference.onDelete !== reference.onDelete) {
|
if (existReference && existReference.onDelete !== reference.onDelete) {
|
||||||
@ -59,6 +59,7 @@ class ReferencesMap {
|
|||||||
|
|
||||||
removeReference(reference: Reference) {
|
removeReference(reference: Reference) {
|
||||||
const references = this.map.get(reference.targetCollectionName);
|
const references = this.map.get(reference.targetCollectionName);
|
||||||
|
|
||||||
if (!references) {
|
if (!references) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,21 @@ export class BelongsToManyField extends RelationField {
|
|||||||
|
|
||||||
const onDelete = this.options.onDelete || 'CASCADE';
|
const onDelete = this.options.onDelete || 'CASCADE';
|
||||||
|
|
||||||
|
const targetAssociation = association.toTarget;
|
||||||
|
|
||||||
|
if (association.targetKey) {
|
||||||
|
targetAssociation.targetKey = association.targetKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceAssociation = association.toSource;
|
||||||
|
|
||||||
|
if (association.sourceKey) {
|
||||||
|
sourceAssociation.targetKey = association.sourceKey;
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
BelongsToField.toReference(db, association.toSource, onDelete),
|
BelongsToField.toReference(db, targetAssociation, onDelete),
|
||||||
BelongsToField.toReference(db, association.toTarget, onDelete),
|
BelongsToField.toReference(db, sourceAssociation, onDelete),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +71,7 @@ export class BelongsToManyField extends RelationField {
|
|||||||
name: through,
|
name: through,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// set through collection schema
|
||||||
if (this.collection.collectionSchema()) {
|
if (this.collection.collectionSchema()) {
|
||||||
throughCollectionOptions['schema'] = this.collection.collectionSchema();
|
throughCollectionOptions['schema'] = this.collection.collectionSchema();
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import Database, { Collection as DBCollection } from '@nocobase/database';
|
import Database from '@nocobase/database';
|
||||||
import { MockServer, mockServer } from '@nocobase/test';
|
import { MockServer, mockServer } from '@nocobase/test';
|
||||||
|
|
||||||
describe('reference integrity check', () => {
|
describe('reference integrity check', () => {
|
||||||
let db: Database;
|
let db: Database;
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = mockServer();
|
app = mockServer({
|
||||||
|
database: {
|
||||||
|
tablePrefix: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await app.db.clean({ drop: true });
|
||||||
db = app.db;
|
db = app.db;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
import Database from '@nocobase/database';
|
||||||
|
import Application from '@nocobase/server';
|
||||||
|
import { createApp } from './index';
|
||||||
|
|
||||||
|
describe('reference integrity check', () => {
|
||||||
|
let db: Database;
|
||||||
|
let app: Application;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = await createApp({
|
||||||
|
database: {
|
||||||
|
tablePrefix: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
db = app.db;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should cascade delete on belongs to many relation on collection', async () => {
|
||||||
|
const users = db.collection({
|
||||||
|
name: 'users',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'belongsToMany',
|
||||||
|
name: 'collections',
|
||||||
|
target: 'collections',
|
||||||
|
sourceKey: 'id',
|
||||||
|
foreignKey: 'user_id',
|
||||||
|
otherKey: 'collection_name',
|
||||||
|
targetKey: 'name',
|
||||||
|
onDelete: 'cascade',
|
||||||
|
through: 'users_collections',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
db.extendCollection({
|
||||||
|
name: 'collections',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'belongsToMany',
|
||||||
|
name: 'users',
|
||||||
|
target: 'users',
|
||||||
|
onDelete: 'cascade',
|
||||||
|
through: 'users_collections',
|
||||||
|
sourceKey: 'name',
|
||||||
|
foreignKey: 'collection_name',
|
||||||
|
otherKey: 'user_id',
|
||||||
|
targetKey: 'id',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sync();
|
||||||
|
|
||||||
|
const postsCollection = await db.getCollection('collections').repository.create({
|
||||||
|
values: {
|
||||||
|
name: 'posts',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const user1 = await users.repository.create({
|
||||||
|
values: {
|
||||||
|
name: 'foo',
|
||||||
|
collections: [postsCollection],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const throughCollection = db.getCollection('users_collections');
|
||||||
|
|
||||||
|
expect(await throughCollection.repository.count()).toEqual(1);
|
||||||
|
await user1.destroy();
|
||||||
|
expect(await throughCollection.repository.count()).toEqual(0);
|
||||||
|
|
||||||
|
const user2 = await users.repository.create({
|
||||||
|
values: {
|
||||||
|
name: 'bar',
|
||||||
|
collections: [postsCollection],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(await throughCollection.repository.count()).toEqual(1);
|
||||||
|
await postsCollection.destroy();
|
||||||
|
expect(await throughCollection.repository.count()).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user