diff --git a/packages/core/database/src/database-utils/index.ts b/packages/core/database/src/database-utils/index.ts new file mode 100644 index 000000000..513ba1d3f --- /dev/null +++ b/packages/core/database/src/database-utils/index.ts @@ -0,0 +1,38 @@ +import Database from '../database'; +import lodash from 'lodash'; + +export default class DatabaseUtils { + constructor(public db: Database) {} + + addSchema(tableName, schema?) { + if (this.db.options.schema) { + schema = this.db.options.schema; + } + + if (schema) { + // @ts-ignore + tableName = this.db.sequelize.getQueryInterface().queryGenerator.addSchema({ + tableName, + _schema: this.db.options.schema, + }); + } + + return tableName; + } + + quoteTable(tableName) { + const queryGenerator = this.db.sequelize.getQueryInterface().queryGenerator; + // @ts-ignore + tableName = queryGenerator.quoteTable(lodash.isPlainObject(tableName) ? tableName : this.addSchema(tableName)); + + return tableName; + } + + schema() { + if (!this.db.inDialect('postgres')) { + return undefined; + } + + return this.db.options.schema || 'public'; + } +} diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 563766056..a1eface0b 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -61,6 +61,8 @@ import { ValidateListener, } from './types'; +import DatabaseUtils from './database-utils'; + export interface MergeOptions extends merge.Options {} export interface PendingOptions { @@ -155,6 +157,7 @@ export class Database extends EventEmitter implements AsyncEmitter { modelCollection = new Map, Collection>(); tableNameCollectionMap = new Map(); + utils = new DatabaseUtils(this); referenceMap = new ReferencesMap(); inheritanceMap = new InheritanceMap(); diff --git a/packages/core/database/src/sync-runner.ts b/packages/core/database/src/sync-runner.ts index a31573ef2..91cf7cae9 100644 --- a/packages/core/database/src/sync-runner.ts +++ b/packages/core/database/src/sync-runner.ts @@ -31,6 +31,9 @@ export class SyncRunner { const tableName = model.tableName; + const schemaTableName = db.utils.addSchema(tableName); + const quoteTableName = db.utils.quoteTable(tableName); + const attributes = model.tableAttributes; const childAttributes = lodash.pickBy(attributes, (value) => { @@ -85,7 +88,7 @@ export class SyncRunner { } } - await this.createTable(tableName, childAttributes, options, model, parentTables, schemaName); + await this.createTable(schemaTableName, childAttributes, options, model, parentTables, db); if (maxSequenceName) { const parentsDeep = Array.from(db.inheritanceMap.getParents(inheritedCollection.name)).map( @@ -134,9 +137,7 @@ WHERE table_name='${queryName}' and column_name='id' and table_schema = '${schem } } - static async createTable(tableName, attributes, options, model, parentTables, schema) { - tableName = model.queryGenerator.addSchema({ tableName, _schema: schema, _schemaDelimiter: '' }); - + static async createTable(tableName, attributes, options, model, parentTables, db) { let sql = ''; options = { ...options }; @@ -161,7 +162,11 @@ WHERE table_name='${queryName}' and column_name='id' and table_schema = '${schem sql = `${queryGenerator.createTableQuery(tableName, attributes, options)}`.replace( ';', - ` INHERITS (${parentTables.map((t) => `"${schema}"."${t}"`).join(', ')});`, + ` INHERITS (${parentTables + .map((t) => { + return db.utils.quoteTable(db.utils.addSchema(t, db.options.schema)); + }) + .join(', ')});`, ); return await model.sequelize.query(sql, options); diff --git a/packages/plugins/duplicator/src/server/restorer.ts b/packages/plugins/duplicator/src/server/restorer.ts index 22f752341..2d20eb030 100644 --- a/packages/plugins/duplicator/src/server/restorer.ts +++ b/packages/plugins/duplicator/src/server/restorer.ts @@ -127,7 +127,7 @@ export class Restorer extends AppMigrator { const metaContent = await fsPromises.readFile(collectionMetaPath, 'utf8'); const meta = JSON.parse(metaContent); - const tableName = this.quoteTable(meta.tableName); + const tableName = this.app.db.utils.quoteTable(meta.tableName); try { // disable trigger @@ -199,25 +199,6 @@ export class Restorer extends AppMigrator { await decompress(backupFilePath, this.workDir); } - quoteTable(tableName) { - // @ts-ignore - tableName = this.app.db.sequelize.getQueryInterface().queryGenerator.quoteTable(this.addSchema(tableName)); - - return tableName; - } - - addSchema(tableName) { - if (this.app.db.options.schema) { - // @ts-ignore - tableName = this.app.db.sequelize.getQueryInterface().queryGenerator.addSchema({ - tableName, - _schema: this.app.db.options.schema, - }); - } - - return tableName; - } - async importCollection(options: { name: string; insert?: boolean; @@ -225,6 +206,8 @@ export class Restorer extends AppMigrator { rowCondition?: (row: any) => boolean; }) { const app = this.app; + const db = app.db; + const collectionName = options.name; const dir = this.workDir; const collection = app.db.getCollection(collectionName); @@ -235,8 +218,8 @@ export class Restorer extends AppMigrator { const meta = JSON.parse(metaContent); app.log.info(`collection meta ${metaContent}`); - const addSchemaTableName = this.addSchema(meta.tableName); - const tableName = this.quoteTable(meta.tableName); + const addSchemaTableName = db.utils.addSchema(meta.tableName); + const tableName = db.utils.quoteTable(meta.tableName); if (options.clear !== false) { // truncate old data