Skip to content

Commit d7e90aa

Browse files
author
Sasha
authored
Merge pull request #77 from ArzamastsevVladyslav/feature/generated-columns
Feature/generated columns
2 parents 8cdcc1d + cb2caa9 commit d7e90aa

File tree

5 files changed

+943
-42
lines changed

5 files changed

+943
-42
lines changed

forward_engineering/alterScript/alterScriptFromDeltaHelper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ const getAlterCollectionsScriptDtos = ({
120120
.filter(Boolean)
121121
.map(item => Object.values(item.properties)[0])
122122
.filter(collection => !collection.compMod)
123-
.flatMap(getModifyColumnScriptDtos(app));
123+
.flatMap(getModifyColumnScriptDtos({app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions}));
124124

125125
return [
126126
...createCollectionsScriptDtos,

forward_engineering/alterScript/alterScriptHelpers/alterEntityHelper.js

Lines changed: 105 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -89,53 +89,63 @@ const getModifyCollectionScriptDtos = (app) => (collection) => {
8989
].filter(Boolean);
9090
}
9191

92+
/**
93+
* @return {(collection: Object, predicate: ([name: string, jsonSchema: Object]) => boolean) => AlterScriptDto[]}
94+
* */
95+
const getAddColumnsByConditionScriptDtos = ({app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions}) =>
96+
(collection, predicate) => {
97+
const _ = app.require('lodash');
98+
const {getEntityName, getNamePrefixedWithSchemaName} = require('../../utils/general')(_);
99+
const {createColumnDefinitionBySchema} = require('./createColumnDefinition')(app);
100+
const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app);
101+
const {getDefinitionByReference} = app.require('@hackolade/ddl-fe-utils');
102+
103+
const collectionSchema = {...collection, ...(_.omit(collection?.role, 'properties') || {})};
104+
const tableName = getEntityName(collectionSchema);
105+
const schemaName = collectionSchema.compMod?.keyspaceName;
106+
const fullName = getNamePrefixedWithSchemaName(tableName, schemaName);
107+
const schemaData = {schemaName, dbVersion};
108+
109+
return _.toPairs(collection.properties)
110+
.filter(([name, jsonSchema]) => predicate([name, jsonSchema]))
111+
.map(([name, jsonSchema]) => {
112+
const definitionJsonSchema = getDefinitionByReference({
113+
propertySchema: jsonSchema,
114+
modelDefinitions,
115+
internalDefinitions,
116+
externalDefinitions,
117+
});
118+
119+
return createColumnDefinitionBySchema({
120+
name,
121+
jsonSchema,
122+
parentJsonSchema: collectionSchema,
123+
ddlProvider,
124+
schemaData,
125+
definitionJsonSchema,
126+
});
127+
})
128+
.map(ddlProvider.convertColumnDefinition)
129+
.map(columnDefinition => ddlProvider.addColumn(fullName, columnDefinition))
130+
.map(addColumnScript => AlterScriptDto.getInstance([addColumnScript], true, false))
131+
.filter(Boolean);
132+
};
133+
92134
/**
93135
* @return {(collection: Object) => AlterScriptDto[]}
94136
* */
95137
const getAddColumnScriptDtos =
96138
({app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions}) =>
97139
collection => {
98-
const _ = app.require('lodash');
99-
const {getEntityName, getNamePrefixedWithSchemaName} = require('../../utils/general')(_);
100-
const {createColumnDefinitionBySchema} = require('./createColumnDefinition')(app);
101-
const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app);
102-
const {getDefinitionByReference} = app.require('@hackolade/ddl-fe-utils');
103-
104-
const collectionSchema = {...collection, ...(_.omit(collection?.role, 'properties') || {})};
105-
const tableName = getEntityName(collectionSchema);
106-
const schemaName = collectionSchema.compMod?.keyspaceName;
107-
const fullName = getNamePrefixedWithSchemaName(tableName, schemaName);
108-
const schemaData = {schemaName, dbVersion};
109-
110-
return _.toPairs(collection.properties)
111-
.filter(([name, jsonSchema]) => !jsonSchema.compMod)
112-
.map(([name, jsonSchema]) => {
113-
const definitionJsonSchema = getDefinitionByReference({
114-
propertySchema: jsonSchema,
115-
modelDefinitions,
116-
internalDefinitions,
117-
externalDefinitions,
118-
});
119-
120-
return createColumnDefinitionBySchema({
121-
name,
122-
jsonSchema,
123-
parentJsonSchema: collectionSchema,
124-
ddlProvider,
125-
schemaData,
126-
definitionJsonSchema,
127-
});
128-
})
129-
.map(ddlProvider.convertColumnDefinition)
130-
.map(columnDefinition => ddlProvider.addColumn(fullName, columnDefinition))
131-
.map(addColumnScript => AlterScriptDto.getInstance([addColumnScript], true, false))
132-
.filter(Boolean);
133-
};
140+
return getAddColumnsByConditionScriptDtos({
141+
app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions
142+
})(collection, ([name, jsonSchema]) => !jsonSchema.compMod);
143+
}
134144

135145
/**
136-
* @return {(collection: Object) => AlterScriptDto[]}
146+
* @return {(collection: Object, predicate: ([name: string, jsonSchema: Object]) => boolean) => AlterScriptDto[]}
137147
* */
138-
const getDeleteColumnScriptDtos = app => collection => {
148+
const getDeleteColumnsByConditionScriptDtos = app => (collection, predicate) => {
139149
const _ = app.require('lodash');
140150
const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app);
141151
const {getEntityName, getNamePrefixedWithSchemaName, wrapInQuotes} = require('../../utils/general')(_);
@@ -146,7 +156,7 @@ const getDeleteColumnScriptDtos = app => collection => {
146156
const fullTableName = getNamePrefixedWithSchemaName(tableName, schemaName);
147157

148158
return _.toPairs(collection.properties)
149-
.filter(([name, jsonSchema]) => !jsonSchema.compMod)
159+
.filter(([name, jsonSchema]) => predicate([name, jsonSchema]))
150160
.map(([name]) => {
151161
const columnNameForDDL = wrapInQuotes(name);
152162
return ddlProvider.dropColumn(fullTableName, columnNameForDDL)
@@ -158,11 +168,66 @@ const getDeleteColumnScriptDtos = app => collection => {
158168
/**
159169
* @return {(collection: Object) => AlterScriptDto[]}
160170
* */
161-
const getModifyColumnScriptDtos = app => collection => {
171+
const getDeleteColumnScriptDtos = app => collection => {
172+
return getDeleteColumnsByConditionScriptDtos(app)(collection, ([name, jsonSchema]) => !jsonSchema.compMod)
173+
};
174+
175+
/**
176+
* @return {(collection: Object) => Array<AlterScriptDto>}
177+
* */
178+
const getDropAndRecreateColumnsScriptDtos = ({app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions}) =>
179+
(collection) => {
180+
const _ = app.require('lodash');
181+
182+
return _.toPairs(collection.properties)
183+
.filter(([name, jsonSchema]) => {
184+
const oldName = jsonSchema.compMod.oldField.name;
185+
const oldProperty = collection.role.properties[oldName];
186+
187+
const didGeneratedColumnChange = oldProperty.generatedColumn !== jsonSchema.generatedColumn
188+
|| oldProperty.columnGenerationExpression !== jsonSchema.columnGenerationExpression;
189+
// all conditions that require drop-and-recreate go here
190+
return didGeneratedColumnChange;
191+
})
192+
.flatMap(([name, jsonSchema]) => {
193+
const collectionWithJustThisProperty = {
194+
...collection,
195+
properties: _.fromPairs([
196+
[name, jsonSchema]
197+
]),
198+
}
199+
const deleteColumnsScriptDtos = getDeleteColumnsByConditionScriptDtos(app)(collectionWithJustThisProperty, () => true);
200+
const addColumnsScriptDtos = getAddColumnsByConditionScriptDtos({
201+
app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions
202+
})(collectionWithJustThisProperty, () => true);
203+
204+
return [
205+
...deleteColumnsScriptDtos,
206+
...addColumnsScriptDtos,
207+
]
208+
})
209+
.filter(Boolean);
210+
}
211+
212+
/**
213+
* @return {(collection: Object) => AlterScriptDto[]}
214+
* */
215+
const getModifyColumnScriptDtos = (
216+
{app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions}
217+
) => collection => {
162218
const _ = app.require('lodash');
163219
const ddlProvider = require('../../ddlProvider/ddlProvider')(null, null, app);
164220

165221
const renameColumnScriptDtos = getRenameColumnScriptDtos(_, ddlProvider)(collection);
222+
223+
const dropAndRecreateScriptDtos = getDropAndRecreateColumnsScriptDtos({app, dbVersion, modelDefinitions, internalDefinitions, externalDefinitions})(collection);
224+
if (dropAndRecreateScriptDtos.length) {
225+
return [
226+
...renameColumnScriptDtos,
227+
...dropAndRecreateScriptDtos,
228+
].filter(Boolean);
229+
}
230+
166231
const updateTypeScriptDtos = getUpdateTypesScriptDtos(_, ddlProvider)(collection);
167232
const modifyNotNullScriptDtos = getModifyNonNullColumnsScriptDtos(_, ddlProvider)(collection);
168233
const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(_, ddlProvider)(collection);

forward_engineering/ddlProvider/ddlProvider.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,17 @@ module.exports = (baseProvider, options, app) => {
258258
const defaultValue = !_.isUndefined(columnDefinition.default)
259259
? ' DEFAULT ' + decorateDefault(type, columnDefinition.default, isArrayType)
260260
: '';
261+
const generatedColumnClause = columnDefinition.generatedColumn && columnDefinition.columnGenerationExpression
262+
? assignTemplates(templates.generatedColumnClause, {
263+
generationExpression: columnDefinition.columnGenerationExpression,
264+
})
265+
: '';
261266

262267
return commentIfDeactivated(
263268
assignTemplates(templates.columnDefinition, {
264269
name: wrapInQuotes(columnDefinition.name),
265270
type: decorateType(type, columnDefinition),
271+
generatedColumnClause,
266272
notNull,
267273
primaryKey,
268274
uniqueKey,
@@ -670,6 +676,8 @@ module.exports = (baseProvider, options, app) => {
670676
timezone,
671677
intervalOptions,
672678
dbVersion,
679+
generatedColumn: Boolean(jsonSchema.generatedColumn),
680+
columnGenerationExpression: jsonSchema.columnGenerationExpression,
673681
};
674682
},
675683

forward_engineering/ddlProvider/templates.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ module.exports = {
1616
'${partitionOf} ${openParenthesis}${keyConstraints}${checkConstraints}${foreignKeyConstraints}\n' +
1717
'${closeParenthesis}${options};\n\n${comment}${columnDescriptions}',
1818

19-
columnDefinition: '${name} ${type}${collation}${primaryKey}${uniqueKey}${defaultValue}${notNull}',
19+
generatedColumnClause: ' GENERATED ALWAYS AS (${generationExpression}) STORED',
20+
21+
columnDefinition: '${name} ${type}${collation}${generatedColumnClause}${primaryKey}${uniqueKey}${defaultValue}${notNull}',
2022

2123
checkConstraint: '${name} CHECK (${expression})${noInherit}',
2224

0 commit comments

Comments
 (0)