diff --git a/packages/core/database/src/__tests__/postgres/schema.test.ts b/packages/core/database/src/__tests__/postgres/schema.test.ts new file mode 100644 index 000000000..b3be47399 --- /dev/null +++ b/packages/core/database/src/__tests__/postgres/schema.test.ts @@ -0,0 +1,63 @@ +import { mockDatabase } from '../index'; +import { Database } from '../../database'; + +describe('postgres schema', () => { + let db: Database; + + beforeEach(async () => { + db = mockDatabase({ + schema: 'test_schema', + }); + + if (!db.inDialect('postgres')) return; + }); + + afterEach(async () => { + if (db.inDialect('postgres')) { + await db.sequelize.query(`DROP SCHEMA IF EXISTS ${db.options.schema} CASCADE;`); + } + await db.close(); + }); + + it('should drop all tables in schemas', async () => { + if (!db.inDialect('postgres')) return; + + const collection = db.collection({ + name: 'test', + }); + + await db.sync(); + + await db.clean({ drop: true }); + + const tableInfo = await db.sequelize.query( + `SELECT * FROM information_schema.tables where table_schema = '${db.options.schema}'`, + ); + + expect(tableInfo[0].length).toEqual(0); + }); + + it('should support database schema option', async () => { + if (!db.inDialect('postgres')) return; + + await db.clean({ drop: true }); + + const tableInfo = await db.sequelize.query( + `SELECT * FROM information_schema.tables where table_schema = '${db.options.schema}'`, + ); + + expect(tableInfo[0].length).toEqual(0); + + const collection = db.collection({ + name: 'test', + }); + + await db.sync(); + + const newTableInfo = await db.sequelize.query( + `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/collection.ts b/packages/core/database/src/collection.ts index fb28a933e..c9ca36bf2 100644 --- a/packages/core/database/src/collection.ts +++ b/packages/core/database/src/collection.ts @@ -7,7 +7,7 @@ import { QueryInterfaceDropTableOptions, SyncOptions, Transactionable, - Utils + Utils, } from 'sequelize'; import { Database } from './database'; import { Field, FieldOptions } from './fields'; diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index b8525c07b..563766056 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'; export interface MergeOptions extends merge.Options {} @@ -484,6 +484,10 @@ export class Database extends EventEmitter implements AsyncEmitter { await this.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null); } + if (this.options.schema && this.inDialect('postgres')) { + await this.sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${this.options.schema}"`, null); + } + const result = await this.sequelize.sync(options); if (isMySQL) { @@ -494,10 +498,29 @@ export class Database extends EventEmitter implements AsyncEmitter { } async clean(options: CleanOptions) { - const { drop, ...others } = options; - if (drop) { - await this.sequelize.getQueryInterface().dropAllTables(others); + const { drop, ...others } = options || {}; + if (drop !== true) { + return; } + + if (this.options.schema) { + const tableNames = (await this.sequelize.getQueryInterface().showAllTables()).map((table) => { + return `"${this.options.schema}"."${table}"`; + }); + + const skip = options.skip || []; + + // @ts-ignore + for (const tableName of tableNames) { + if (skip.includes(tableName)) { + continue; + } + await this.sequelize.query(`DROP TABLE IF EXISTS ${tableName} CASCADE`); + } + return; + } + + await this.sequelize.getQueryInterface().dropAllTables(others); } async collectionExistsInDb(name, options?: Transactionable) {