diff --git a/packages/core/database/src/__tests__/postgres/schema.test.ts b/packages/core/database/src/__tests__/postgres/schema.test.ts index b3be47399..07d3ccf5e 100644 --- a/packages/core/database/src/__tests__/postgres/schema.test.ts +++ b/packages/core/database/src/__tests__/postgres/schema.test.ts @@ -1,5 +1,36 @@ import { mockDatabase } from '../index'; import { Database } from '../../database'; +import { randomStr } from '@nocobase/test'; + +describe('auth', () => { + let db: Database; + afterEach(async () => { + if (db) { + await db.close(); + } + }); + + it('should auto create schema on prepare when schema missing', async () => { + const schemaName = randomStr(); + + db = mockDatabase({ + schema: schemaName, + }); + + if (!db.inDialect('postgres')) return; + + const querySchemaExists = async () => + await db.sequelize.query( + `SELECT schema_name + FROM information_schema.schemata + WHERE schema_name = '${schemaName}';`, + ); + + expect((await querySchemaExists())[0].length).toEqual(0); + await db.prepare(); + expect((await querySchemaExists())[0].length).toEqual(1); + }); +}); describe('postgres schema', () => { let db: Database; @@ -31,7 +62,9 @@ describe('postgres schema', () => { await db.clean({ drop: true }); const tableInfo = await db.sequelize.query( - `SELECT * FROM information_schema.tables where table_schema = '${db.options.schema}'`, + `SELECT * + FROM information_schema.tables + where table_schema = '${db.options.schema}'`, ); expect(tableInfo[0].length).toEqual(0); @@ -43,7 +76,9 @@ describe('postgres schema', () => { await db.clean({ drop: true }); const tableInfo = await db.sequelize.query( - `SELECT * FROM information_schema.tables where table_schema = '${db.options.schema}'`, + `SELECT * + FROM information_schema.tables + where table_schema = '${db.options.schema}'`, ); expect(tableInfo[0].length).toEqual(0); @@ -55,7 +90,9 @@ describe('postgres schema', () => { await db.sync(); const newTableInfo = await db.sequelize.query( - `SELECT * FROM information_schema.tables where table_schema = '${db.options.schema}'`, + `SELECT * + FROM information_schema.tables + where table_schema = '${db.options.schema}'`, ); expect(newTableInfo[0].find((item) => item['table_name'] == collection.model.tableName)).toBeTruthy(); diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 270c43ccb..a58db3bf9 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -15,7 +15,7 @@ import { Sequelize, SyncOptions, Transactionable, - Utils + Utils, } from 'sequelize'; import { SequelizeStorage, Umzug } from 'umzug'; import { Collection, CollectionOptions, RepositoryType } from './collection'; @@ -58,7 +58,7 @@ import { SyncListener, UpdateListener, UpdateWithAssociationsListener, - ValidateListener + ValidateListener, } from './types'; import { patchSequelizeQueryInterface, snakeCase } from './utils'; @@ -653,6 +653,12 @@ export class Database extends EventEmitter implements AsyncEmitter { return await authenticate(); } + async prepare() { + if (this.inDialect('postgres') && this.options.schema && this.options.schema != 'public') { + await this.sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${this.options.schema}"`, null); + } + } + async reconnect() { if (this.isSqliteMemory()) { return; diff --git a/packages/core/server/src/application.ts b/packages/core/server/src/application.ts index b0838456b..077beff83 100644 --- a/packages/core/server/src/application.ts +++ b/packages/core/server/src/application.ts @@ -377,8 +377,11 @@ export class Application exten console.log(chalk.red(error.message)); process.exit(1); } + await this.dbVersionCheck({ exit: true }); + await this.db.prepare(); + if (argv?.[2] !== 'upgrade') { await this.load({ method: argv?.[2], diff --git a/packages/core/test/src/index.ts b/packages/core/test/src/index.ts index 89d3610cc..08c9f5ebf 100644 --- a/packages/core/test/src/index.ts +++ b/packages/core/test/src/index.ts @@ -3,3 +3,8 @@ export * from './mockServer'; const pgOnly: () => jest.Describe = () => (process.env.DB_DIALECT == 'postgres' ? describe : describe.skip); export { pgOnly }; + +export function randomStr() { + // create random string + return Math.random().toString(36).substring(2); +}