fix(m2m-array): check naming collision (#5059)

This commit is contained in:
YANG QIA 2024-08-15 11:55:36 +08:00 committed by GitHub
parent b15a635ee8
commit 161407c803
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 24 deletions

View File

@ -78,8 +78,8 @@ describe('belongs to array field', () => {
describe('association keys check', async () => {
it('targetKey is required', async () => {
try {
await db.sequelize.transaction(async (transaction) => {
await expect(
db.sequelize.transaction(async (transaction) => {
const field = await fieldRepo.create({
values: {
interface: 'mbm',
@ -92,15 +92,13 @@ describe('belongs to array field', () => {
transaction,
});
await field.load({ transaction });
});
} catch (error) {
expect(error.message).toContain('Target key is required');
}
}),
).rejects.toThrow(/Target key is required/);
});
it('foreign field must be an array or set field', async () => {
try {
await db.sequelize.transaction(async (transaction) => {
await expect(
db.sequelize.transaction(async (transaction) => {
const field = await fieldRepo.create({
values: {
interface: 'mbm',
@ -114,20 +112,16 @@ describe('belongs to array field', () => {
transaction,
});
await field.load({ transaction });
});
} catch (error) {
expect(error.message).toContain(
'The type of foreign key "username" in collection "users" must be ARRAY, JSON or JSONB',
);
}
}),
).rejects.toThrow(/The type of foreign key "username" in collection "users" must be ARRAY, JSON or JSONB/);
});
it('element type of foreign field must be match the type of target field', async () => {
if (db.sequelize.getDialect() !== 'postgres') {
return;
}
try {
await db.sequelize.transaction(async (transaction) => {
await expect(
db.sequelize.transaction(async (transaction) => {
const field = await fieldRepo.create({
values: {
interface: 'mbm',
@ -141,14 +135,12 @@ describe('belongs to array field', () => {
transaction,
});
await field.load({ transaction });
});
} catch (error) {
expect(error.message).toContain(
'The element type "STRING" of foreign key "tag_ids" does not match the type "BIGINT" of target key "id" in collection "tags"',
}),
).rejects.toThrow(
/The element type "STRING" of foreign key "tag_ids" does not match the type "BIGINT" of target key "id" in collection "tags"/,
);
}
expect(
await expect(
db.sequelize.transaction(async (transaction) => {
const field = await fieldRepo.create({
values: {
@ -166,5 +158,25 @@ describe('belongs to array field', () => {
}),
).resolves.not.toThrow();
});
it('the name of foreign key must not be the same as the name of the field', async () => {
await expect(
db.sequelize.transaction(async (transaction) => {
const field = await fieldRepo.create({
values: {
interface: 'mbm',
collectionName: 'users',
name: 'tag_ids_same',
type: 'belongsToArray',
foreignKey: 'tag_ids_same',
target: 'tags',
targetKey: 'stringCode',
},
transaction,
});
await field.load({ transaction });
}),
).rejects.toThrow(/Naming collision/);
});
});
});

View File

@ -12,10 +12,15 @@ import { elementTypeMap } from '../belongs-to-array-field';
export const createForeignKey = (db: Database) => {
return async (model: Model, { transaction }) => {
const { type, collectionName, target, targetKey, foreignKey } = model.get();
const { type, collectionName, target, targetKey, foreignKey, name } = model.get();
if (type !== 'belongsToArray') {
return;
}
if (name === foreignKey) {
throw new Error(
`Naming collision between attribute '${foreignKey}' and association '${name}' on model ${collectionName}. To remedy this, change either foreignKey or as in your association definition`,
);
}
const r = db.getRepository('fields');
const instance = await r.findOne({
filter: {