diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index 4eb9a01..8306a52 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -9,7 +9,7 @@ const { getAddForeignKeyScriptDtos, getModifyForeignKeyScriptDtos, } = require('./alterScriptHelpers/alterForeignKeyHelper'); -const { getModifyViewScriptDtos } = require('./alterScriptHelpers/alterViewHelper'); +const { getViewsScripts } = require('./alterScriptHelpers/alterViewHelper'); /** * @param {T} data @@ -100,8 +100,8 @@ const getAlterCollectionScriptDtos = ({ return [ ...deletedCollectionScriptDtos, ...addedCollectionScriptDtos, - ...modifyCollectionScriptDtos, ...deletedColumnScriptDtos, + ...modifyCollectionScriptDtos, ...addedColumnScriptDtos, ...modifyColumnScriptDtos, ...modifyCollectionKeysScriptDtos, @@ -110,15 +110,32 @@ const getAlterCollectionScriptDtos = ({ /** * @param {Object} collection + * @param {App} app * @return {Array} */ -const getAlterViewScriptDtos = collection => { - const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified) - .map(viewWrapper => Object.values(viewWrapper.properties)[0]) +const getAlterViewScriptDtos = (collection, app) => { + const { added, deleted, modified } = collection.properties?.views?.properties || {}; + const { getAddViewScriptDto, getDeleteViewScriptDto, getModifyViewScriptDtos } = getViewsScripts(app); + + const addedViews = getItems(added) + .map(item => Object.values(item.properties)[0]) .map(view => ({ ...view, ...view.role })) - .flatMap(getModifyViewScriptDtos); + .filter(view => view.compMod?.created); + + const deletedViews = getItems(deleted) + .map(item => Object.values(item.properties)[0]) + .map(view => ({ ...view, ...view.role })) + .filter(view => view.compMod?.deleted); + + const modifiedViews = getItems(modified) + .map(item => Object.values(item.properties)[0]) + .map(view => ({ ...view, ...view.role })); + + const addedViewScriptDtos = addedViews.map(getAddViewScriptDto); + const deletedViewScriptDtos = deletedViews.map(getDeleteViewScriptDto); + const modifyViewScriptDtos = modifiedViews.flatMap(getModifyViewScriptDtos); - return [...modifyViewScriptDtos].filter(Boolean); + return [...deletedViewScriptDtos, ...addedViewScriptDtos, ...modifyViewScriptDtos].filter(Boolean); }; /** @@ -238,7 +255,7 @@ const getAlterScriptDtos = (data, app) => { inlineDeltaRelationships, }); - const viewScriptDtos = getAlterViewScriptDtos(collection); + const viewScriptDtos = getAlterViewScriptDtos(collection, app); const relationshipScriptDtos = getAlterRelationshipsScriptDtos({ collection, diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js index 68a6a4a..0148f52 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js @@ -21,6 +21,7 @@ const { } = require('../../utils/general'); const { getRelationshipName } = require('./alterForeignKeyHelper'); const { createColumnDefinitionBySchema } = require('./createColumnDefinition'); +const { getRenameTableScriptDtos } = require('./entityHelpers/alterTableNameHelper'); /** * @param {Object} ddlProvider @@ -99,9 +100,12 @@ const getDeleteCollectionScriptDto = ddlProvider => collection => { * @returns {Array} */ const getModifyCollectionScriptDtos = collection => { + const modifyCollectionNameScriptDtos = getRenameTableScriptDtos(collection); const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(collection); const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(collection); - return [...modifyCheckConstraintScriptDtos, ...modifyCommentScriptDtos].filter(Boolean); + return [...modifyCollectionNameScriptDtos, ...modifyCheckConstraintScriptDtos, ...modifyCommentScriptDtos].filter( + Boolean, + ); }; /** diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js index c38dd89..ae0f447 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js @@ -1,11 +1,64 @@ +/** + * @typedef {import('../../../shared/types').App} App + */ const { getModifyViewCommentsScriptDtos } = require('./viewHelpers/commentsHelper'); +const { getRenameViewScriptDtos } = require('./viewHelpers/alterNameHelper'); +const { AlterScriptDto } = require('../types/AlterScriptDto'); +const { getSchemaOfAlterCollection } = require('../../utils/general'); +const { createView, dropView } = require('./viewHelpers/createDropViewHelper'); +const { getModifySelectStatementScriptDtos } = require('./viewHelpers/alterViewStatementHelper'); -const getModifyViewScriptDtos = view => { +/** + * @param {Object} ddlProvider + * @param {Function} mapProperties + * @returns {(view: Object) => AlterScriptDto} + */ +const getAddViewScriptDto = (ddlProvider, mapProperties) => view => { + const script = createView({ ddlProvider, mapProperties, view }); + + return AlterScriptDto.getInstance([script], true, false); +}; + +/** + * @param {Object} ddlProvider + * @returns {(view: Object) => AlterScriptDto} + */ +const getDeleteViewScriptDto = ddlProvider => view => { + const viewSchema = getSchemaOfAlterCollection(view); + const script = dropView({ ddlProvider, viewSchema }); + + return AlterScriptDto.getInstance([script], true, true); +}; + +/** + * @param {Object} ddlProvider + * @param {Function} mapProperties + * @returns {(view: Object) => Array} + */ +const getModifyViewScriptDtos = (ddlProvider, mapProperties) => view => { + const renameViewNameScriptDtos = getRenameViewScriptDtos(view, ddlProvider, mapProperties); + const modifySelectStatementScriptDtos = getModifySelectStatementScriptDtos(view, ddlProvider, mapProperties); const modifyCommentsScriptDtos = getModifyViewCommentsScriptDtos(view); - return [...modifyCommentsScriptDtos].filter(Boolean); + return [...renameViewNameScriptDtos, ...modifySelectStatementScriptDtos, ...modifyCommentsScriptDtos].filter( + Boolean, + ); +}; + +/** + * @param {App} app + */ +const getViewsScripts = app => { + const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app); + const { mapProperties } = app.require('@hackolade/ddl-fe-utils'); + + return { + getAddViewScriptDto: getAddViewScriptDto(ddlProvider, mapProperties), + getDeleteViewScriptDto: getDeleteViewScriptDto(ddlProvider), + getModifyViewScriptDtos: getModifyViewScriptDtos(ddlProvider, mapProperties), + }; }; module.exports = { - getModifyViewScriptDtos, + getViewsScripts, }; diff --git a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js index 485f048..4b78ce1 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/columnHelpers/commentsHelper.js @@ -6,7 +6,10 @@ const { getSchemaOfAlterCollection, getFullCollectionName, } = require('../../../utils/general'); -const { getColumnCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); +const { + getColumnCommentStatement, + dropTableColumnCommentStatement, +} = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); const getUpdatedCommentOnColumnScriptDtos = collection => { const isContainerActivated = isParentContainerActivated(collection); @@ -46,7 +49,7 @@ const getDeletedCommentOnColumnScriptDtos = collection => { }) .map(([columnName, jsonSchema]) => { const isActivated = isContainerActivated && isCollectionActivated && jsonSchema.isActivated; - const script = getColumnCommentStatement({ tableName, columnName, description: '' }); + const script = dropTableColumnCommentStatement({ tableName, columnName }); return { script, isActivated }; }) diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/alterTableNameHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/alterTableNameHelper.js new file mode 100644 index 0000000..d39adf1 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/alterTableNameHelper.js @@ -0,0 +1,53 @@ +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { + isParentContainerActivated, + isObjectInDeltaModelActivated, + getSchemaOfAlterCollection, + getSchemaNameFromCollection, + getNamePrefixedWithSchemaName, +} = require('../../../utils/general'); +const { assignTemplates } = require('../../../utils/assignTemplates'); +const templates = require('../../../ddlProvider/templates'); + +/** + * @param {string} oldTableName + * @param {string} newTableName + * @return string + */ +const alterTableName = (oldTableName, newTableName) => { + return assignTemplates({ template: templates.renameTable, templateData: { oldTableName, newTableName } }); +}; + +/** + * @param {Object} collection + * @returns {Array} + */ +const getRenameTableScriptDtos = collection => { + const collectionSchema = getSchemaOfAlterCollection(collection); + const tableName = collectionSchema?.compMod?.collectionName; + + if (!tableName) { + return []; + } + + const { old: oldName, new: newName } = tableName; + + if (!newName || newName === oldName) { + return []; + } + + const schemaName = getSchemaNameFromCollection({ collection: collectionSchema }); + const isContainerActivated = isParentContainerActivated(collection); + const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); + + const script = alterTableName( + getNamePrefixedWithSchemaName({ name: oldName, schemaName }), + getNamePrefixedWithSchemaName({ name: newName, schemaName }), + ); + + return [AlterScriptDto.getInstance([script], isCollectionActivated, false)]; +}; + +module.exports = { + getRenameTableScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js index b9e3a6c..f5efe69 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/entityHelpers/commentsHelper.js @@ -6,7 +6,10 @@ const { getSchemaOfAlterCollection, getFullCollectionName, } = require('../../../utils/general'); -const { getTableCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); +const { + getTableCommentStatement, + dropTableCommentStatement, +} = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); const getUpdatedCommentOnCollectionScriptDto = collection => { const descriptionInfo = collection?.role.compMod?.description; @@ -46,7 +49,7 @@ const getDeletedCommentOnCollectionScriptDto = collection => { const isContainerActivated = isParentContainerActivated(collection); const isCollectionActivated = isContainerActivated && isObjectInDeltaModelActivated(collection); - const script = getTableCommentStatement({ tableName, description: '' }); + const script = dropTableCommentStatement({ tableName }); return AlterScriptDto.getInstance([script], isCollectionActivated, true); }; diff --git a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterNameHelper.js b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterNameHelper.js new file mode 100644 index 0000000..225acce --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterNameHelper.js @@ -0,0 +1,39 @@ +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { getSchemaOfAlterCollection } = require('../../../utils/general'); +const { createView, dropView } = require('./createDropViewHelper'); + +/** + * @param {Object} view + * @param {Object} ddlProvider + * @param {Function} mapProperties + * @return {AlterScriptDto | undefined} + */ +const getRenameViewScriptDtos = (view, ddlProvider, mapProperties) => { + const viewSchema = getSchemaOfAlterCollection(view); + const viewName = viewSchema?.compMod?.name; + + if (!viewName) { + return [undefined]; + } + + const { old: oldName, new: newName } = viewName; + + if (!newName || newName === oldName) { + return [undefined]; + } + + const dropScript = dropView({ + ddlProvider, + viewSchema: { ...viewSchema, code: oldName, name: oldName }, + }); + const createScript = createView({ ddlProvider, mapProperties, view }); + + return [ + AlterScriptDto.getInstance([dropScript], true, true), + AlterScriptDto.getInstance([createScript], true, false), + ]; +}; + +module.exports = { + getRenameViewScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterViewStatementHelper.js b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterViewStatementHelper.js new file mode 100644 index 0000000..92dabce --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/alterViewStatementHelper.js @@ -0,0 +1,30 @@ +const { getSchemaOfAlterCollection } = require('../../../utils/general'); +const { AlterScriptDto } = require('../../types/AlterScriptDto'); +const { createView, dropView } = require('./createDropViewHelper'); + +/** + * @param {Object} view + * @param {Object} ddlProvider + * @param {Function} mapProperties + * @returns {AlterScriptDto | undefined} + */ +const getModifySelectStatementScriptDtos = (view, ddlProvider, mapProperties) => { + const viewSchema = getSchemaOfAlterCollection(view); + const selectStatement = viewSchema?.compMod?.selectStatement || {}; + + if ((!selectStatement.new && !selectStatement.old) || selectStatement.new === selectStatement.old) { + return [undefined]; + } + + const dropScript = dropView({ viewSchema, ddlProvider }); + const createScript = createView({ ddlProvider, mapProperties, view }); + + return [ + AlterScriptDto.getInstance([dropScript], true, true), + AlterScriptDto.getInstance([createScript], true, false), + ]; +}; + +module.exports = { + getModifySelectStatementScriptDtos, +}; diff --git a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js index 89bab01..61615f2 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/commentsHelper.js @@ -5,7 +5,10 @@ const { getFullCollectionName, getSchemaOfAlterCollection, } = require('../../../utils/general'); -const { getTableCommentStatement } = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); +const { + getTableCommentStatement, + dropTableCommentStatement, +} = require('../../../ddlProvider/ddlHelpers/comment/commentHelper'); const extractDescription = view => { return view?.role?.compMod?.description || {}; @@ -39,7 +42,7 @@ const getDropCommentsScriptDto = view => { const isContainerActivated = isParentContainerActivated(view); const isViewActivated = isContainerActivated && isObjectInDeltaModelActivated(view); - const script = getTableCommentStatement({ tableName: viewName, description: '' }); + const script = dropTableCommentStatement({ tableName: viewName }); return AlterScriptDto.getInstance([script], isViewActivated, true); } return undefined; diff --git a/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/createDropViewHelper.js b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/createDropViewHelper.js new file mode 100644 index 0000000..c3151e6 --- /dev/null +++ b/forward_engineering/alterScript/alterScriptHelpers/viewHelpers/createDropViewHelper.js @@ -0,0 +1,103 @@ +const { get } = require('lodash'); +const { + getSchemaOfAlterCollection, + getSchemaNameFromCollection, + getFullCollectionName, +} = require('../../../utils/general'); + +/** + * @param {{ + * viewSchema: Object, + * collectionRefsDefinitionsMap: Object, + * mapProperties: Function, + * ddlProvider: Object + * }} param + */ +const getKeys = ({ viewSchema, collectionRefsDefinitionsMap, mapProperties, ddlProvider }) => { + return mapProperties(viewSchema, (propertyName, schema) => { + const definition = collectionRefsDefinitionsMap[schema.refId]; + + if (!definition) { + return ddlProvider.hydrateViewColumn({ + name: propertyName, + isActivated: schema.isActivated, + }); + } + + const entityName = + get(definition.collection, '[0].code', '') || get(definition.collection, '[0].collectionName', '') || ''; + const dbName = get(definition.bucket, '[0].code') || get(definition.bucket, '[0].name', ''); + const name = definition.name; + + if (name === propertyName) { + return ddlProvider.hydrateViewColumn({ + containerData: definition.bucket, + entityData: definition.collection, + isActivated: schema.isActivated, + definition: definition.definition, + entityName, + name, + dbName, + }); + } + + return ddlProvider.hydrateViewColumn({ + containerData: definition.bucket, + entityData: definition.collection, + isActivated: schema.isActivated, + definition: definition.definition, + alias: propertyName, + entityName, + name, + dbName, + }); + }); +}; + +/** + * @param {{ + * ddlProvider: Object, + * mapProperties: Function, + * view: Object + * }} param + * @returns {string} + */ +const createView = ({ ddlProvider, mapProperties, view }) => { + const viewSchema = getSchemaOfAlterCollection(view); + const schemaName = getSchemaNameFromCollection({ collection: viewSchema }) || ''; + const schemaData = { schemaName }; + + const viewData = { + name: viewSchema.code || viewSchema.name, + keys: getKeys({ + viewSchema, + ddlProvider, + mapProperties, + collectionRefsDefinitionsMap: view.compMod?.collectionData?.collectionRefsDefinitionsMap ?? {}, + }), + schemaData, + }; + + const hydratedView = ddlProvider.hydrateView({ viewData, entityData: [viewSchema] }); + const script = ddlProvider.createView(hydratedView, {}, viewSchema.isActivated); + + return script; +}; + +/** + * @param {{ + * ddlProvider: Object, + * viewSchema: Object + * }} param + * @returns {string} + */ +const dropView = ({ ddlProvider, viewSchema }) => { + const viewName = getFullCollectionName(viewSchema); + + return ddlProvider.dropView({ viewName }); +}; + +module.exports = { + createView, + dropView, +}; diff --git a/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js b/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js index 3ca70c6..e5d85a6 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js +++ b/forward_engineering/ddlProvider/ddlHelpers/comment/commentHelper.js @@ -130,6 +130,31 @@ const dropSchemaCommentStatement = ({ schemaName }) => { }); }; +/** + * @param {{ tableName: string }} + * @returns {string} + */ +const dropTableCommentStatement = ({ tableName }) => { + return getCommentStatement({ + objectName: tableName, + objectType: OBJECT_TYPE.table, + mode: COMMENT_MODE.remove, + }); +}; + +/** + * @param {{ tableName: string, columnName: string }} + * @returns {string} + */ +const dropTableColumnCommentStatement = ({ tableName, columnName }) => { + const objectName = tableName + '.' + wrapInQuotes(columnName); + return getCommentStatement({ + objectName, + objectType: OBJECT_TYPE.column, + mode: COMMENT_MODE.remove, + }); +}; + module.exports = { getColumnCommentStatement, getSchemaCommentStatement, @@ -138,4 +163,6 @@ module.exports = { getIndexCommentStatement, dropSchemaCommentStatement, + dropTableCommentStatement, + dropTableColumnCommentStatement, }; diff --git a/forward_engineering/ddlProvider/ddlProvider.js b/forward_engineering/ddlProvider/ddlProvider.js index 6933aed..c9a824b 100644 --- a/forward_engineering/ddlProvider/ddlProvider.js +++ b/forward_engineering/ddlProvider/ddlProvider.js @@ -419,6 +419,10 @@ module.exports = (baseProvider, options, app) => { return assignTemplates({ template: templates.dropColumn, templateData: { tableName, columnName } }); }, + dropView({ viewName }) { + return assignTemplates({ template: templates.dropView, templateData: { viewName } }); + }, + hydrateIndex(indexData, tableData, schemaData) { return { ...indexData, schemaName: schemaData.schemaName }; }, diff --git a/forward_engineering/ddlProvider/templates.js b/forward_engineering/ddlProvider/templates.js index 1d73c01..57906fc 100644 --- a/forward_engineering/ddlProvider/templates.js +++ b/forward_engineering/ddlProvider/templates.js @@ -62,4 +62,8 @@ module.exports = { dropColumnDefaultValue: 'ALTER TABLE ${tableName} ALTER COLUMN ${columnName} DROP DEFAULT;', renameColumn: 'ALTER TABLE ${tableName} RENAME COLUMN ${oldColumnName} TO ${newColumnName};', + + dropView: 'DROP VIEW ${viewName};', + + renameTable: 'RENAME TABLE ${oldTableName} TO ${newTableName};', };