diff --git a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js index b4e4ef9..ddc03c4 100644 --- a/forward_engineering/alterScript/alterScriptFromDeltaHelper.js +++ b/forward_engineering/alterScript/alterScriptFromDeltaHelper.js @@ -228,8 +228,11 @@ const getAlterViewsScriptDtos = (schema, provider, _, dbVersion) => { .map(view => ({ ...view, ...(view.role || {}) })) .filter(view => !view.compMod?.created && !view.compMod?.deleted) .flatMap(getScript); - - const addedViewScriptDtos = getViewScripts(getItems(schema, 'views', 'added'), 'created', getAddViewsScripts(_)); + const addedViewScriptDtos = getViewScripts( + getItems(schema, 'views', 'added'), + 'created', + getAddViewsScripts(provider, _), + ); const deletedViewScriptDtos = getViewScripts( getItems(schema, 'views', 'deleted'), 'deleted', diff --git a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js index b435daa..28536f9 100644 --- a/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js +++ b/forward_engineering/alterScript/alterScriptHelpers/alterViewHelper.js @@ -1,4 +1,3 @@ -const { getViewScript } = require('../../helpers/viewHelper'); const { hydrateTableProperties } = require('../../helpers/tableHelper'); const { getEntityData, @@ -87,9 +86,10 @@ const hydrateAlterView = _ => view => { /** * @return {(view: Object) => AlterScriptDto} * */ -const getAddViewsScripts = _ => view => { +const getAddViewsScripts = (provider, _) => view => { const hydratedView = hydrateView(_)(view); - const script = getViewScript({ _, ...hydratedView }); + const script = provider.createView(hydratedView); + return { isActivated: true, scripts: [ @@ -137,7 +137,7 @@ const getModifyViewsScripts = (provider, _, dbVersion) => view => { } const dropViewScript = provider.dropView(viewName); const hydratedView = hydrateView(_)(view); - const addViewScript = getViewScript({ _, ...hydratedView }); + const addViewScript = provider.createView(hydratedView); const dropViewScriptDto = AlterScriptDto.getInstance([dropViewScript], true, true); const addViewScriptDto = AlterScriptDto.getInstance([addViewScript], true, false); diff --git a/forward_engineering/api.js b/forward_engineering/api.js index b7f73c5..0d974b4 100644 --- a/forward_engineering/api.js +++ b/forward_engineering/api.js @@ -1,7 +1,6 @@ 'use strict'; const { getDatabaseStatement, getUseCatalogStatement } = require('./helpers/databaseHelper'); -const { getViewScript } = require('./helpers/viewHelper'); const { getCleanedUrl, buildScript, isSupportUnityCatalog, getDBVersionNumber } = require('./utils/general'); const fetchRequestHelper = require('../reverse_engineering/helpers/fetchRequestHelper'); const databricksHelper = require('../reverse_engineering/helpers/databricksHelper'); @@ -259,7 +258,7 @@ module.exports = { * */ generateViewScript(data, logger, callback, app) { try { - const _ = app.require('lodash'); + const provider = require('./ddlProvider/ddlProvider')(app); const viewSchema = JSON.parse(data.jsonSchema || '{}'); const dbVersion = data.modelData[0].dbVersion; const isUnityCatalogSupports = isSupportUnityCatalog(dbVersion); @@ -267,8 +266,7 @@ module.exports = { const useCatalogStatement = isUnityCatalogSupports ? getUseCatalogStatement(data.containerData) : ''; const databaseStatement = getDatabaseStatement(data.containerData, isUnityCatalogSupports, dbVersion); - const script = getViewScript({ - _, + const script = provider.createView({ schema: viewSchema, viewData: data.viewData, containerData: data.containerData, diff --git a/forward_engineering/ddlProvider/ddlProvider.js b/forward_engineering/ddlProvider/ddlProvider.js index 7d7da8e..b76515e 100644 --- a/forward_engineering/ddlProvider/ddlProvider.js +++ b/forward_engineering/ddlProvider/ddlProvider.js @@ -1,13 +1,76 @@ const templates = require('./ddlTemplates'); -const { getFullEntityName } = require('../utils/general'); +const { + getFullEntityName, + getName, + replaceSpaceWithUnderscore, + prepareName, + getContainerName, + getEntityData, + getEntityProperties, + wrapInBrackets, +} = require('../utils/general'); +const { getViewTagsStatement } = require('../helpers/unityTagsHelper'); +const { getTablePropertiesClause } = require('../helpers/tableHelper'); +const viewHelper = require('../helpers/viewHelper'); module.exports = app => { const { assignTemplates } = app.require('@hackolade/ddl-fe-utils'); + const _ = app.require('lodash'); + return { dropView(name) { return assignTemplates(templates.dropView, { name }); }, + createView(data) { + const { schema, viewData, containerData, collectionRefsDefinitionsMap } = data; + + const columns = schema.properties || {}; + const view = _.first(viewData) || {}; + + if (!view.isActivated) { + return; + } + + const bucketName = replaceSpaceWithUnderscore(prepareName(viewHelper.retrieveContainerName(containerData))); + const viewName = replaceSpaceWithUnderscore(prepareName(view.code || view.name)); + const isGlobal = schema.viewGlobal && schema.viewTemporary; + const isTemporary = schema.viewTemporary; + const orReplace = schema.viewOrReplace; + const ifNotExists = view.viewIfNotExist; + const name = bucketName ? `${bucketName}.${viewName}` : `${viewName}`; + const tableProperties = + schema.tableProperties && Array.isArray(schema.tableProperties) + ? viewHelper.filterRedundantProperties(schema.tableProperties, ['transient_lastDdlTime']) + : []; + const viewUnityTagsStatements = + schema.unityViewTags && getViewTagsStatement({ viewSchema: schema, viewName: name }); + + return assignTemplates(templates.createView, { + orReplace: orReplace && !ifNotExists ? ' OR REPLACE' : '', + global: isGlobal ? ' GLOBAL' : '', + temporary: isTemporary ? ' TEMPORARY' : '', + ifNotExists: ifNotExists ? ' IF NOT EXISTS' : '', + name, + columnList: view.columnList + ? `${wrapInBrackets(view.columnList)}` + : viewHelper.getDefaultColumnList(columns), + schemaBinding: '', + comment: viewHelper.getCommentStatement(schema.description), + tablePropertyStatements: tableProperties.length + ? `TBLPROPERTIES (${getTablePropertiesClause(_)(tableProperties)})` + : '', + query: schema.selectStatement + ? `AS ${schema.selectStatement}` + : viewHelper.getTableSelectStatement({ + _, + collectionRefsDefinitionsMap, + columns, + }), + viewUnityTagsStatements: viewUnityTagsStatements ? `${viewUnityTagsStatements};` : '', + }); + }, + dropTableIndex(name) { return name ? assignTemplates(templates.dropTableIndex, { name }) : ''; }, diff --git a/forward_engineering/ddlProvider/ddlTemplates.js b/forward_engineering/ddlProvider/ddlTemplates.js index 8d3d5a2..726fc83 100644 --- a/forward_engineering/ddlProvider/ddlTemplates.js +++ b/forward_engineering/ddlProvider/ddlTemplates.js @@ -1,6 +1,7 @@ module.exports = { createView: - 'CREATE ${orReplace}${global}${temporary} VIEW${ifNotExists} ${name}${columnList}${schemaBinding}${comment}${tablePropertyStatements}${query};${viewUnityTagsStatements}', + 'CREATE${orReplace}${global}${temporary} VIEW${ifNotExists} ${name} ${columnList}${schemaBinding}${comment}${tablePropertyStatements}${query};${viewUnityTagsStatements}', + dropView: 'DROP VIEW IF EXISTS ${name};', alterViewName: 'ALTER VIEW ${oldName} RENAME TO ${newName};', diff --git a/forward_engineering/helpers/feScriptBuilder.js b/forward_engineering/helpers/feScriptBuilder.js index 42ae4cf..8b7ea13 100644 --- a/forward_engineering/helpers/feScriptBuilder.js +++ b/forward_engineering/helpers/feScriptBuilder.js @@ -131,13 +131,12 @@ const buildEntityLevelFEScript = * @param _ {any} * @return {Array} * */ -const getContainerLevelViewScriptDtos = (data, _) => { +const getContainerLevelViewScriptDtos = (data, provider, _) => { return data.views .map(viewId => { const viewSchema = JSON.parse(data.jsonSchema[viewId] || '{}'); const viewData = data.viewData[viewId]; - const viewScript = getViewScript({ - _, + const viewScript = provider.createView({ schema: viewSchema, viewData: viewData, containerData: data.containerData, @@ -295,8 +294,9 @@ const buildContainerLevelFEScriptDto = const arePkFkConstraintsAvailable = isSupportUnityCatalog(dbVersion); const areNotNullConstraintsAvailable = isSupportNotNullConstraints(dbVersion); + const provider = require('../ddlProvider/ddlProvider')(app); const useCatalogStatement = arePkFkConstraintsAvailable ? getUseCatalogStatement(containerData) : ''; - const viewsScriptDtos = getContainerLevelViewScriptDtos(data, _); + const viewsScriptDtos = getContainerLevelViewScriptDtos(data, provider, _); const databaseStatement = getDatabaseStatement(containerData, arePkFkConstraintsAvailable, dbVersion); const entityScriptDtos = await getContainerLevelEntitiesScriptDtos( app, diff --git a/forward_engineering/helpers/viewHelper.js b/forward_engineering/helpers/viewHelper.js index 29588b3..95492b9 100644 --- a/forward_engineering/helpers/viewHelper.js +++ b/forward_engineering/helpers/viewHelper.js @@ -1,10 +1,6 @@ 'use strict'; const { prepareName, encodeStringLiteral, commentDeactivatedStatement } = require('../utils/general'); -const { getTablePropertiesClause } = require('./tableHelper'); -const { getViewTagsStatement } = require('./unityTagsHelper'); -const ddlTemplates = require('../ddlProvider/ddlTemplates'); -const assignTemplates = require('../utils/assignTemplates'); const getColumnNames = _ => (collectionRefsDefinitionsMap, columns) => { return _.uniq( @@ -121,53 +117,6 @@ function getTableSelectStatement({ _, collectionRefsDefinitionsMap, columns }) { return ''; } -module.exports = { - getViewScript({ _, schema, viewData, containerData, collectionRefsDefinitionsMap }) { - const columns = schema.properties || {}; - const view = _.first(viewData) || {}; - - if (!view.isActivated) { - return; - } - - const bucketName = replaceSpaceWithUnderscore(prepareName(retrieveContainerName(containerData))); - const viewName = replaceSpaceWithUnderscore(prepareName(view.code || view.name)); - const isGlobal = schema.viewGlobal && schema.viewTemporary; - const isTemporary = schema.viewTemporary; - const orReplace = schema.viewOrReplace; - const ifNotExists = view.viewIfNotExist; - const name = bucketName ? `${bucketName}.${viewName}` : `${viewName}`; - const tableProperties = - schema.tableProperties && Array.isArray(schema.tableProperties) - ? filterRedundantProperties(schema.tableProperties, ['transient_lastDdlTime']) - : []; - const viewUnityTagsStatements = - schema.unityViewTags && getViewTagsStatement({ viewSchema: schema, viewName: name }); - - return assignTemplates(ddlTemplates.createView, { - orReplace: orReplace && !ifNotExists ? 'OR REPLACE ' : '', - global: isGlobal ? 'GLOBAL ' : '', - temporary: isTemporary ? 'TEMPORARY ' : '', - ifNotExists: ifNotExists ? ' IF NOT EXISTS' : '', - name, - columnList: view.columnList ? `\n(${view.columnList})` : getDefaultColumnList(columns), - schemaBinding: '', - comment: getCommentStatement(schema.description), - tablePropertyStatements: tableProperties.length - ? `\nTBLPROPERTIES (${getTablePropertiesClause(_)(tableProperties)})` - : '', - query: schema.selectStatement - ? `\nAS ${schema.selectStatement}` - : getTableSelectStatement({ - _, - collectionRefsDefinitionsMap, - columns, - }), - viewUnityTagsStatements: viewUnityTagsStatements ? `\n${viewUnityTagsStatements};` : '', - }); - }, -}; - const filterRedundantProperties = (tableProperties, propertiesList) => { if (!Array.isArray(tableProperties)) { return tableProperties; @@ -175,3 +124,11 @@ const filterRedundantProperties = (tableProperties, propertiesList) => { return tableProperties.filter(prop => !propertiesList.includes(prop.propertyKey)); }; + +module.exports = { + getTableSelectStatement, + retrieveContainerName, + filterRedundantProperties, + getDefaultColumnList, + getCommentStatement, +}; diff --git a/forward_engineering/utils/assignTemplates.js b/forward_engineering/utils/assignTemplates.js deleted file mode 100644 index 4ae512e..0000000 --- a/forward_engineering/utils/assignTemplates.js +++ /dev/null @@ -1,15 +0,0 @@ -const template = (modifiers = '') => new RegExp('\\$\\{(.*?)}', modifiers); -const getAllTemplates = str => str.match(template('gi')) || []; -const parseTemplate = str => (str.match(template('i')) || [])[1]; - -const assignTemplates = (str, templates) => { - return getAllTemplates(str).reduce((result, item) => { - const templateName = parseTemplate(item); - - return result.replace(item, () => { - return templates[templateName] || templates[templateName] === 0 ? templates[templateName] : ''; - }); - }, str); -}; - -module.exports = assignTemplates; diff --git a/forward_engineering/utils/general.js b/forward_engineering/utils/general.js index 0695438..15640df 100644 --- a/forward_engineering/utils/general.js +++ b/forward_engineering/utils/general.js @@ -180,7 +180,7 @@ const wrapInTicks = (str = '') => { }; const wrapInBrackets = (str = '') => { - return /^\(\S+\)$/.test(str) ? str : `(${str})`; + return /^\(.*\)$/.test(str) ? str : `(${str})`; }; /**