diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/view/view-collection.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/view/view-collection.test.ts index 90c3413a1..223dad029 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/view/view-collection.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/view/view-collection.test.ts @@ -1,4 +1,4 @@ -import Database, { Field, Repository, ViewCollection, ViewFieldInference, DataTypes } from '@nocobase/database'; +import Database, { Repository, ViewCollection, ViewFieldInference } from '@nocobase/database'; import Application from '@nocobase/server'; import { uid } from '@nocobase/utils'; import { createApp } from '../index'; @@ -28,6 +28,65 @@ describe('view collection', function () { await app.destroy(); }); + it('should use id field as only primary key', async () => { + await collectionRepository.create({ + values: { + name: 'groups', + fields: [{ name: 'name', type: 'string' }], + }, + context: {}, + }); + + await collectionRepository.create({ + values: { + name: 'users', + fields: [ + { name: 'name', type: 'string' }, + { type: 'belongsTo', name: 'group', foreignKey: 'group_id' }, + ], + }, + context: {}, + }); + + const User = db.getCollection('users'); + + const assoc = User.model.associations.group; + const foreignKey = assoc.foreignKey; + const foreignField = User.model.rawAttributes[foreignKey].field; + + const viewName = `test_view_${uid(6)}`; + await db.sequelize.query(`DROP VIEW IF EXISTS ${viewName}`); + + const createSQL = `CREATE VIEW ${viewName} AS SELECT id, ${foreignField}, name FROM ${db + .getCollection('users') + .quotedTableName()}`; + + await db.sequelize.query(createSQL); + + const inferredFields = await ViewFieldInference.inferFields({ + db, + viewName, + viewSchema: 'public', + }); + + await collectionRepository.create({ + values: { + name: viewName, + view: true, + fields: [ + { name: 'id', type: 'bigInt' }, + { name: 'group_id', type: 'bigInt', primaryKey: true }, + { name: 'name', type: 'string' }, + ], + schema: db.inDialect('postgres') ? 'public' : undefined, + }, + context: {}, + }); + + const viewCollection = db.getCollection(viewName); + expect(viewCollection.model.primaryKeyAttributes).toEqual(['id']); + }); + it('should create view collection with belongs to association', async () => { await collectionRepository.create({ values: { diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/models/collection.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/models/collection.ts index 248c070eb..f861dfc16 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/server/models/collection.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/models/collection.ts @@ -78,6 +78,18 @@ export class CollectionModel extends MagicAttributeModel { fields = fields.filter((field) => options.includeFields.includes(field.name)); } + if (this.options.view && fields.find((f) => f.name == 'id')) { + // set id field to primary key, other primary key to false + fields = fields.map((field) => { + if (field.name == 'id') { + field.set('primaryKey', true); + } else { + field.set('primaryKey', false); + } + return field; + }); + } + // @ts-ignore const instances: FieldModel[] = fields;