diff --git a/packages/core/database/src/sync-runner.ts b/packages/core/database/src/sync-runner.ts index 18272e3241..a31573ef23 100644 --- a/packages/core/database/src/sync-runner.ts +++ b/packages/core/database/src/sync-runner.ts @@ -7,6 +7,8 @@ export class SyncRunner { const inheritedCollection = model.collection as InheritedCollection; const db = inheritedCollection.context.database; + const schemaName = db.options.schema || 'public'; + const dialect = db.sequelize.getDialect(); const queryInterface = db.sequelize.getQueryInterface(); @@ -27,7 +29,7 @@ export class SyncRunner { const parentTables = parents.map((parent) => parent.model.tableName); - const tableName = model.getTableName(); + const tableName = model.tableName; const attributes = model.tableAttributes; @@ -44,6 +46,7 @@ export class SyncRunner { `SELECT column_default FROM information_schema.columns WHERE table_name = '${parent}' + and table_schema = '${schemaName}' and "column_name" = 'id';`, { transaction, @@ -60,7 +63,7 @@ export class SyncRunner { throw new Error(`Can't find sequence name of ${parent}`); } - const regex = new RegExp(/nextval\('("?\w+"?)\'.*\)/); + const regex = new RegExp(/nextval\('(.*)'::regclass\)/); const match = regex.exec(columnDefault); const sequenceName = match[1]; @@ -82,25 +85,24 @@ export class SyncRunner { } } - await this.createTable(tableName, childAttributes, options, model, parentTables); + await this.createTable(tableName, childAttributes, options, model, parentTables, schemaName); if (maxSequenceName) { const parentsDeep = Array.from(db.inheritanceMap.getParents(inheritedCollection.name)).map( (parent) => db.getCollection(parent).model.tableName, ); - const sequenceTables = [...parentsDeep, tableName]; + const sequenceTables = [...parentsDeep, tableName.toString()]; for (const sequenceTable of sequenceTables) { - const queryName = Boolean(sequenceTable.match(/[A-Z]/)) ? `"${sequenceTable}"` : sequenceTable; + const queryName = + Boolean(sequenceTable.match(/[A-Z]/)) && !sequenceTable.includes(`"`) ? `"${sequenceTable}"` : sequenceTable; const idColumnQuery = await queryInterface.sequelize.query( ` - SELECT true - FROM pg_attribute - WHERE attrelid = '${queryName}'::regclass -- cast to a registered class (table) -AND attname = 'id' -AND NOT attisdropped + SELECT column_name +FROM information_schema.columns +WHERE table_name='${queryName}' and column_name='id' and table_schema = '${schemaName}'; `, { transaction, @@ -112,7 +114,7 @@ AND NOT attisdropped } await queryInterface.sequelize.query( - `alter table "${sequenceTable}" + `alter table "${schemaName}"."${sequenceTable}" alter column id set default nextval('${maxSequenceName}')`, { transaction, @@ -132,7 +134,9 @@ AND NOT attisdropped } } - static async createTable(tableName, attributes, options, model, parentTables) { + static async createTable(tableName, attributes, options, model, parentTables, schema) { + tableName = model.queryGenerator.addSchema({ tableName, _schema: schema, _schemaDelimiter: '' }); + let sql = ''; options = { ...options }; @@ -157,7 +161,7 @@ AND NOT attisdropped sql = `${queryGenerator.createTableQuery(tableName, attributes, options)}`.replace( ';', - ` INHERITS (${parentTables.map((t) => `"${t}"`).join(', ')});`, + ` INHERITS (${parentTables.map((t) => `"${schema}"."${t}"`).join(', ')});`, ); return await model.sequelize.query(sql, options); diff --git a/packages/plugins/collection-manager/src/__tests__/inherits/inherited-collection.test.ts b/packages/plugins/collection-manager/src/__tests__/inherits/inherited-collection.test.ts index 60f9543842..dc7f898bd0 100644 --- a/packages/plugins/collection-manager/src/__tests__/inherits/inherited-collection.test.ts +++ b/packages/plugins/collection-manager/src/__tests__/inherits/inherited-collection.test.ts @@ -3,6 +3,56 @@ import Application from '@nocobase/server'; import { createApp } from '..'; import { pgOnly } from '@nocobase/test'; +pgOnly()('Inherited Collection', () => { + let db: Database; + let app: Application; + + let collectionRepository: Repository; + + let fieldsRepository: Repository; + + beforeEach(async () => { + app = await createApp({ + database: { + schema: 'testSchema', + }, + }); + + db = app.db; + + collectionRepository = db.getCollection('collections').repository; + fieldsRepository = db.getCollection('fields').repository; + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('should create inherited collection in difference schema', async () => { + await collectionRepository.create({ + values: { + name: 'b', + fields: [ + { + name: 'name', + type: 'string', + }, + ], + }, + context: {}, + }); + + await collectionRepository.create({ + values: { + name: 'a', + inherits: ['b'], + fields: [{ type: 'string', name: 'bField' }], + }, + context: {}, + }); + }); +}); + pgOnly()('Inherited Collection', () => { let db: Database; let app: Application;