diff --git a/forward_engineering/configs/templates.js b/forward_engineering/configs/templates.js index f34ff843..52e0c9f5 100644 --- a/forward_engineering/configs/templates.js +++ b/forward_engineering/configs/templates.js @@ -26,7 +26,7 @@ module.exports = { createView: 'CREATE${secure}${materialized} VIEW IF NOT EXISTS ${name} (\n' + '\t${column_list}\n' + - ')\n${copy_grants}${comment}${tag}AS ${select_statement};\n', + ')\n${copy_grants}${comment}${tag}${clustering}AS ${select_statement};\n', createUDF: 'CREATE${orReplace} FUNCTION ${name}(${arguments})\n\tRETURNS ${returnType}${notNull}\n\tLANGUAGE ${language}${parameters}${comment}\n\tAS ${body};\n', createProcedure: diff --git a/forward_engineering/ddlProvider.js b/forward_engineering/ddlProvider.js index 75e11b96..79de9f8a 100644 --- a/forward_engineering/ddlProvider.js +++ b/forward_engineering/ddlProvider.js @@ -530,15 +530,23 @@ module.exports = (baseProvider, options, app) => { indent: '', }); + const clustering = viewData.materialized + ? keyHelper.getClusteringKey({ + clusteringKey: viewData.clusteringKey, + isParentActivated: isActivated, + }) + : undefined; + return assignTemplates(templates.createView, { secure: viewData.secure ? ' SECURE' : '', materialized: viewData.materialized ? ' MATERIALIZED' : '', name: getFullName(schemaName, viewData.name), column_list: viewColumnsToString(columnList, isActivated), copy_grants: viewData.copyGrants ? 'COPY GRANTS\n' : '', - comment: viewData.comment ? 'COMMENT=' + escapeString(scriptFormat, viewData.comment) + '\n' : '', + comment: viewData.comment ? `COMMENT=${escapeString(scriptFormat, viewData.comment)}\n` : '', select_statement: selectStatement, tag: tagStatement ? tagStatement + '\n' : '', + clustering, }); }, @@ -877,6 +885,7 @@ module.exports = (baseProvider, options, app) => { secure: firstTab.secure, materialized: firstTab.materialized, fullName, + clusteringKey: firstTab.clusteringKey, viewTags: firstTab.viewTags ?? [], }; }, diff --git a/forward_engineering/helpers/general.js b/forward_engineering/helpers/general.js index ea72d92b..4435fa84 100644 --- a/forward_engineering/helpers/general.js +++ b/forward_engineering/helpers/general.js @@ -258,6 +258,7 @@ module.exports = app => { getEntityName, getFullName, getDbName, + addQuotes, getGroupItemsByCompMode, }; }; diff --git a/forward_engineering/helpers/keyHelper.js b/forward_engineering/helpers/keyHelper.js index ddd294c7..967721ee 100644 --- a/forward_engineering/helpers/keyHelper.js +++ b/forward_engineering/helpers/keyHelper.js @@ -2,6 +2,7 @@ const _ = require('lodash'); module.exports = app => { const { clean } = app.require('@hackolade/ddl-fe-utils').general; + const { addQuotes } = require('./general')(app); const mapProperties = (jsonSchema, iteratee) => { return Object.entries(jsonSchema.properties).map(iteratee); @@ -131,7 +132,44 @@ module.exports = app => { ]; }; + /** + * @typedef {{ isActivated: boolean, name: string }} ClusteringKey + * @param {{ clusteringKey: ClusteringKey[], isParentActivated: boolean }} clusteringKeyArgs + * @returns {string} + */ + const getClusteringKey = ({ clusteringKey, isParentActivated }) => { + if (!Array.isArray(clusteringKey) || clusteringKey.length === 0) { + return ''; + } + + const mapName = ({ name }) => addQuotes(name); + + const activated = clusteringKey + .filter(key => key.isActivated) + .map(mapName) + .join(', '); + const deactivated = clusteringKey + .filter(key => !key.isActivated) + .map(mapName) + .join(', '); + + if (!isParentActivated) { + return `CLUSTER BY (${clusteringKey.map(mapName).join(', ')})\n`; + } + + if (activated.length === 0) { + return `// CLUSTER BY (${deactivated})\n`; + } + + if (deactivated.length === 0) { + return `CLUSTER BY (${activated})\n`; + } + + return `CLUSTER BY (${activated}) //${deactivated}\n`; + }; + return { getTableKeyConstraints, + getClusteringKey, }; }; diff --git a/properties_pane/view_level/viewLevelConfig.json b/properties_pane/view_level/viewLevelConfig.json index 5c6e01af..dfdab135 100644 --- a/properties_pane/view_level/viewLevelConfig.json +++ b/properties_pane/view_level/viewLevelConfig.json @@ -56,6 +56,23 @@ "propertyTooltip": "is Materialized View", "propertyType": "checkbox" }, + { + "propertyName": "Cluster by", + "propertyKeyword": "clusteringKey", + "dependency": { + "key": "materialized", + "value": true + }, + "propertyType": "fieldList", + "disabledItemStrategy": "default", + "abbr": "CK", + "setPrimaryKey": false, + "template": "orderedList", + "isCompositeKey": true, + "templateOptions": { + "maxFields": 4 + } + }, { "propertyName": "Secure", "propertyKeyword": "secure",