diff --git a/integration-tests/__tests__/deploy-database.spec.js b/integration-tests/__tests__/deploy-database.spec.js index 7fe885d4d..b75347989 100644 --- a/integration-tests/__tests__/deploy-database.spec.js +++ b/integration-tests/__tests__/deploy-database.spec.js @@ -1,55 +1,41 @@ /// TODO -const stableStringify = require('json-stable-stringify'); -const _ = require('lodash'); -const fp = require('lodash/fp'); -const uuidv1 = require('uuid/v1'); const { testWrapper } = require('../tools'); const engines = require('../engines'); -const { getAlterDatabaseScript, extendDatabaseInfo, generateDbPairingId } = require('dbgate-tools'); +const deployDb = require('dbgate-api/src/shell/deployDb'); -function flatSource() { - return _.flatten( - engines.map(engine => (engine.objects || []).map(object => [engine.label, object.type, object, engine])) - ); -} +async function testDatabaseDeploy(conn, driver, dbModelYaml, checkDb) { + await deployDb({ + systemConnection: conn, + driver, + loadedDbModel: dbModelYaml, + }); -async function testDatabaseDiff(conn, driver, mangle, createObject = null) { - await driver.query(conn, `create table t1 (id int not null primary key)`); - - await driver.query( - conn, - `create table t2 ( - id int not null primary key, - t1_id int null references t1(id) - )` - ); - - if (createObject) await driver.query(conn, createObject); - - const structure1 = generateDbPairingId(extendDatabaseInfo(await driver.analyseFull(conn))); - let structure2 = _.cloneDeep(structure1); - mangle(structure2); - structure2 = extendDatabaseInfo(structure2); - - const { sql } = getAlterDatabaseScript(structure1, structure2, {}, structure2, driver); - console.log('RUNNING ALTER SQL', driver.engine, ':', sql); - - await driver.script(conn, sql); - - const structure2Real = extendDatabaseInfo(await driver.analyseFull(conn)); - - expect(structure2Real.tables.length).toEqual(structure2.tables.length); - return structure2Real; + const structure = await driver.analyseFull(conn); + checkDb(structure); } describe('Deploy database', () => { test.each(engines.map(engine => [engine.label, engine]))( 'Drop referenced table - %s', testWrapper(async (conn, driver, engine) => { - await testDatabaseDiff(conn, driver, db => { - _.remove(db.tables, x => x.pureName == 't1'); - }); + await testDatabaseDeploy( + conn, + driver, + [ + { + name: 'tables.yaml', + json: { + name: 't1', + columns: [{ name: 'id', type: 'int' }], + primaryKey: ['id'], + }, + }, + ], + db => { + expect(db.tables.length).toEqual(1); + } + ); }) ); }); diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index b13671bce..1662af13c 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -12,6 +12,7 @@ const { archivedir } = require('../utility/directories'); const path = require('path'); const importDbModel = require('../utility/importDbModel'); const requireEngineDriver = require('../utility/requireEngineDriver'); +const generateDeploySql = require('../shell/generateDeploySql'); module.exports = { /** @type {import('dbgate-types').OpenedDatabaseConnection[]} */ @@ -257,19 +258,25 @@ module.exports = { generateDeploySql_meta: 'post', async generateDeploySql({ conid, database, archiveFolder }) { - const deployedModel = generateDbPairingId(await importDbModel(path.join(archivedir(), archiveFolder))); - const currentModel = generateDbPairingId(await this.structure({ conid, database })); - const currentModelPaired = matchPairedObjects(deployedModel, currentModel); const connection = await connections.get({ conid }); - const driver = requireEngineDriver(connection); - const { sql } = getAlterDatabaseScript(currentModelPaired, deployedModel, {}, deployedModel, driver); - return { - deployedModel, - currentModel, - currentModelPaired, - sql, - }; - return sql; + return generateDeploySql({ + connection, + analysedStructure: await this.structure({ conid, database }), + modelFolder: path.join(archivedir(), archiveFolder), + }); + // const deployedModel = generateDbPairingId(await importDbModel(path.join(archivedir(), archiveFolder))); + // const currentModel = generateDbPairingId(await this.structure({ conid, database })); + // const currentModelPaired = matchPairedObjects(deployedModel, currentModel); + // const connection = await connections.get({ conid }); + // const driver = requireEngineDriver(connection); + // const { sql } = getAlterDatabaseScript(currentModelPaired, deployedModel, {}, deployedModel, driver); + // return { + // deployedModel, + // currentModel, + // currentModelPaired, + // sql, + // }; + // return sql; }, // runCommand_meta: 'post', // async runCommand({ conid, database, sql }) { diff --git a/packages/api/src/shell/deployDb.js b/packages/api/src/shell/deployDb.js index a2fe4cf2b..c20d9e380 100644 --- a/packages/api/src/shell/deployDb.js +++ b/packages/api/src/shell/deployDb.js @@ -1,8 +1,16 @@ -const EnsureStreamHeaderStream = require('../utility/EnsureStreamHeaderStream'); -const importDbModel = require('../utility/importDbModel'); +const generateDeploySql = require('./generateDeploySql'); +const executeQuery = require('./executeQuery'); -async function deployDb(connection, modelFolder, options) { - const dbModel = await importDbModel(modelFolder); +async function deployDb({ connection, systemConnection, driver, analysedStructure, modelFolder, loadedDbModel }) { + const sql = await generateDeploySql({ + connection, + systemConnection, + driver, + analysedStructure, + modelFolder, + loadedDbModel, + }); + await executeQuery({ connection, systemConnection, driver, sql }); } module.exports = deployDb; diff --git a/packages/api/src/shell/executeQuery.js b/packages/api/src/shell/executeQuery.js index 536617bea..39c5bdb3b 100644 --- a/packages/api/src/shell/executeQuery.js +++ b/packages/api/src/shell/executeQuery.js @@ -2,11 +2,11 @@ const { splitQuery } = require('dbgate-query-splitter'); const requireEngineDriver = require('../utility/requireEngineDriver'); const connectUtility = require('../utility/connectUtility'); -async function executeQuery({ connection, sql }) { +async function executeQuery({ connection = undefined, systemConnection = undefined, driver = undefined, sql }) { console.log(`Execute query ${sql}`); - const driver = requireEngineDriver(connection); - const pool = await connectUtility(driver, connection); + if (!driver) driver = requireEngineDriver(connection); + const pool = systemConnection || (await connectUtility(driver, connection)); console.log(`Connected.`); for (const sqlItem of splitQuery(sql, driver.getQuerySplitterOptions('script'))) { diff --git a/packages/api/src/shell/generateDeploySql.js b/packages/api/src/shell/generateDeploySql.js new file mode 100644 index 000000000..0253e64be --- /dev/null +++ b/packages/api/src/shell/generateDeploySql.js @@ -0,0 +1,34 @@ +const { + getAlterDatabaseScript, + generateDbPairingId, + matchPairedObjects, + databaseInfoFromYamlModel, +} = require('dbgate-tools'); +const importDbModel = require('../utility/importDbModel'); +const requireEngineDriver = require('../utility/requireEngineDriver'); +const connectUtility = require('../utility/connectUtility'); + +async function generateDeploySql({ + connection, + systemConnection = undefined, + driver = undefined, + analysedStructure = undefined, + modelFolder = undefined, + loadedDbModel = undefined, +}) { + if (!driver) driver = requireEngineDriver(connection); + if (!analysedStructure) { + const pool = systemConnection || (await connectUtility(driver, connection)); + analysedStructure = await driver.analyseFull(pool); + } + + const deployedModel = generateDbPairingId( + loadedDbModel ? databaseInfoFromYamlModel(loadedDbModel) : await importDbModel(modelFolder) + ); + const currentModel = generateDbPairingId(analysedStructure); + const currentModelPaired = matchPairedObjects(deployedModel, currentModel); + const { sql } = getAlterDatabaseScript(currentModelPaired, deployedModel, {}, deployedModel, driver); + return sql; +} + +module.exports = generateDeploySql;