From c750bd04adb8b346d19cc8cce8cd56f426cb8414 Mon Sep 17 00:00:00 2001 From: "SPRINX0\\prochazka" Date: Fri, 8 Nov 2024 09:12:28 +0100 Subject: [PATCH] export model - filter by schema --- packages/api/package.json | 1 - .../src/controllers/databaseConnections.js | 9 ++++-- packages/api/src/utility/exportDbModelSql.js | 30 ++++++++++++++----- packages/tools/src/structureTools.ts | 26 ++++++++++++++++ packages/types/dbinfo.d.ts | 1 - yarn.lock | 5 ---- 6 files changed, 54 insertions(+), 18 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index 0ac1c406f..41d6b6746 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -49,7 +49,6 @@ "jsonwebtoken": "^8.5.1", "line-reader": "^0.4.0", "lodash": "^4.17.21", - "mkdirp": "^3.0.1", "moment": "^2.24.0", "ncp": "^2.0.0", "node-cron": "^2.0.3", diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index 6bd86c03c..5fc2bed2f 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -13,6 +13,7 @@ const { modelCompareDbDiffOptions, getLogger, extractErrorLogData, + filterStructureBySchema, } = require('dbgate-tools'); const { html, parse } = require('diff2html'); const { handleProcessCommunication } = require('../utility/processComm'); @@ -448,7 +449,8 @@ module.exports = { : outputFolder; const model = await this.structure({ conid, database }); - await exportDbModel(extendDatabaseInfo(model), realFolder); + const filteredModel = schema ? filterStructureBySchema(model, schema) : model; + await exportDbModel(extendDatabaseInfo(filteredModel), realFolder); if (outputFolder.startsWith('archive:')) { socket.emitChanged(`archive-files-changed`, { folder: outputFolder.substring('archive:'.length) }); @@ -457,14 +459,15 @@ module.exports = { }, exportModelSql_meta: true, - async exportModelSql({ conid, database, outputFolder, outputFile }, req) { + async exportModelSql({ conid, database, outputFolder, outputFile, schema }, req) { testConnectionPermission(conid, req); const connection = await connections.getCore({ conid }); const driver = requireEngineDriver(connection); const model = await this.structure({ conid, database }); - await exportDbModelSql(extendDatabaseInfo(model), driver, outputFolder, outputFile); + const filteredModel = schema ? filterStructureBySchema(model, schema) : model; + await exportDbModelSql(extendDatabaseInfo(filteredModel), driver, outputFolder, outputFile); return { status: 'ok' }; }, diff --git a/packages/api/src/utility/exportDbModelSql.js b/packages/api/src/utility/exportDbModelSql.js index 65aa92fbd..4875aeb77 100644 --- a/packages/api/src/utility/exportDbModelSql.js +++ b/packages/api/src/utility/exportDbModelSql.js @@ -1,11 +1,21 @@ const fs = require('fs-extra'); const path = require('path'); -const yaml = require('js-yaml'); -const { mkdirp } = require('mkdirp'); +const { getSchemasUsedByStructure } = require('dbgate-tools'); async function exportDbModelSql(dbModel, driver, outputDir, outputFile) { const { tables, views, procedures, functions, triggers, matviews } = dbModel; + const usedSchemas = getSchemasUsedByStructure(dbModel); + const useSchemaDir = usedSchemas.length > 1; + + const createdDirs = new Set(); + async function ensureDir(dir) { + if (!createdDirs.has(dir)) { + await fs.mkdir(dir, { recursive: true }); + createdDirs.add(dir); + } + } + async function writeLists(writeList) { await writeList(views, 'views'); await writeList(procedures, 'procedures'); @@ -39,25 +49,29 @@ async function exportDbModelSql(dbModel, driver, outputDir, outputFile) { } if (outputDir) { - await mkdirp(path.join(outputDir, 'tables')); for (const table of tables || []) { + const tablesDir = useSchemaDir + ? path.join(outputDir, table.schemaName ?? 'default', 'tables') + : path.join(outputDir, 'tables'); + await ensureDir(tablesDir); const dmp = driver.createDumper(); dmp.createTable({ ...table, foreignKeys: [], dependencies: [], }); - await fs.writeFile(path.join(outputDir, 'tables', `${table.pureName}.sql`), dmp.s); + await fs.writeFile(path.join(tablesDir, `${table.pureName}.sql`), dmp.s); } await writeLists(async (list, folder) => { - if (list.length > 0) { - await mkdirp(path.join(outputDir, folder)); - } for (const obj of list || []) { + const objdir = useSchemaDir + ? path.join(outputDir, obj.schemaName ?? 'default', folder) + : path.join(outputDir, folder); + await ensureDir(objdir); const dmp = driver.createDumper(); dmp.createSqlObject(obj); - await fs.writeFile(path.join(outputDir, folder, `${obj.pureName}.sql`), dmp.s); + await fs.writeFile(path.join(objdir, `${obj.pureName}.sql`), dmp.s); } }); } diff --git a/packages/tools/src/structureTools.ts b/packages/tools/src/structureTools.ts index 0ef7b9aca..4d676bfa0 100644 --- a/packages/tools/src/structureTools.ts +++ b/packages/tools/src/structureTools.ts @@ -1,5 +1,6 @@ import type { DatabaseInfo, TableInfo, ApplicationDefinition, ViewInfo, CollectionInfo } from 'dbgate-types'; import _flatten from 'lodash/flatten'; +import _uniq from 'lodash/uniq'; export function addTableDependencies(db: DatabaseInfo): DatabaseInfo { if (!db.tables) { @@ -142,3 +143,28 @@ export function isViewInfo(obj: { objectTypeField?: string }): obj is ViewInfo { export function isCollectionInfo(obj: { objectTypeField?: string }): obj is CollectionInfo { return obj.objectTypeField == 'collections'; } + +export function filterStructureBySchema(db: DatabaseInfo, schema: string) { + return { + ...db, + tables: (db.tables || []).filter(x => x.schemaName == schema), + views: (db.views || []).filter(x => x.schemaName == schema), + collections: (db.collections || []).filter(x => x.schemaName == schema), + matviews: (db.matviews || []).filter(x => x.schemaName == schema), + procedures: (db.procedures || []).filter(x => x.schemaName == schema), + functions: (db.functions || []).filter(x => x.schemaName == schema), + triggers: (db.triggers || []).filter(x => x.schemaName == schema), + }; +} + +export function getSchemasUsedByStructure(db: DatabaseInfo) { + return _uniq([ + ...(db.tables || []).map(x => x.schemaName), + ...(db.views || []).map(x => x.schemaName), + ...(db.collections || []).map(x => x.schemaName), + ...(db.matviews || []).map(x => x.schemaName), + ...(db.procedures || []).map(x => x.schemaName), + ...(db.functions || []).map(x => x.schemaName), + ...(db.triggers || []).map(x => x.schemaName), + ]); +} diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 74bd6da2c..92644d453 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -3,7 +3,6 @@ export interface NamedObjectInfo { schemaName?: string; contentHash?: string; engine?: string; - undropPureName?: string; } export interface ColumnReference { diff --git a/yarn.lock b/yarn.lock index 3c5b61754..527c1ffa6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8390,11 +8390,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== - moment@^2.24.0, moment@^2.29.2: version "2.30.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"