Skip to content

Commit

Permalink
Feature/implement generated as (#152)
Browse files Browse the repository at this point in the history
* HCK-9065: update adapters to handle new GENERATED AS property structure (#151)

* HCK-9065: add 'identity' to 'generated as' adapter

* HCK-9065: update polyglot adapters

* HCK-9063: Add support for GENERATED ALWAYS AS an expression (#150)

* HCK-9063: add field level config for generated as property

* HCK-9063: add generated as clause in script

* HCK-9063: improve config dependency

* HCK-9063: fix generated on null property
  • Loading branch information
serhii-filonenko authored Dec 12, 2024
1 parent b2ed55a commit dcae3a8
Show file tree
Hide file tree
Showing 7 changed files with 878 additions and 157 deletions.
99 changes: 99 additions & 0 deletions adapter/0.2.22.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* Copyright © 2016-2018 by IntegrIT S.A. dba Hackolade. All rights reserved.
*
* The copyright to the computer software herein is the property of IntegrIT S.A.
* The software may be used and/or copied only with the written permission of
* IntegrIT S.A. or in accordance with the terms and conditions stipulated in
* the agreement/contract under which the software has been supplied.
*
* {
* "add": {
* "entity": [<names of new property>],
* "container": [<names of new property>],
* "model": [<names of new property>],
* "view": [<names of new property>],
* "field": {
* "<type>": [<names of new property>]
* }
* },
* "delete": {
* "entity": [<names of new property>],
* "container": [<names of new property>],
* "model": [<names of new property>],
* "view": [<names of new property>],
* "field": {
* "<type>": [<names of new property>]
* }
* },
* "modify": {
* "entity": [
* {
* "from": { <properties that identify record> },
* "to": { <properties that need to be changed> }
* }
* ],
* "container": [],
* "model": [],
* "view": [],
* "field": []
* },
* }
*/
{
"add": {},
"modify": {
"field": [
[
"assignProperties",
{
"key": "identity",
"valueType": "object"
},
{
"generatedDefaultValue": {
"asIdentity": true,
"generatedType": ""
}
}
],
[
"movePropertyByPath",
{
"from": "identity",
"to": "generatedDefaultValue.identity"
}
],
[
"movePropertyByPath",
{
"from": "generatedDefaultValue.identity.generated",
"to": "generatedDefaultValue.generatedType"
}
],
[
"movePropertyByPath",
{
"from": "generatedDefaultValue.identity.generatedOnNull",
"to": "generatedDefaultValue.generatedOnNull"
}
],
[
"addMissingIdByPath",
{
"from": "generatedDefaultValue",
"path": "generatedDefaultValue.GUID"
}
]
]
},
"delete": {
"number": [
{
"path": "generatedDefaultValue.identity.generated"
},
{
"path": "generatedDefaultValue.identity.generatedOnNull"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const _ = require('lodash');
const { DbVersion } = require('../../enums/DbVersion');
const { getColumnDefault } = require('../ddlHelpers/columnDefinitionHelpers/getColumnDefault');
/**
* @param dbVersion {string} DB version in "21&i" format
* @return {boolean}
Expand Down Expand Up @@ -55,32 +56,6 @@ module.exports = ({ _, wrap, assignTemplates, templates, commentIfDeactivated, w
return type;
};

const getColumnDefault = ({ default: defaultValue, defaultOnNull, identity }) => {
if (!_.isEmpty(identity) && identity.generated) {
const getGenerated = ({ generated, generatedOnNull }) => {
if (generated === 'BY DEFAULT') {
return ` ${generated} ${generatedOnNull ? ' ON NULL' : ''}`;
} else {
return ` ALWAYS`;
}
};

const getOptions = ({ identityStart, identityIncrement, numberToCache }) => {
const startWith = identityStart ? ` START WITH ${identityStart}` : '';
const incrementBy = identityIncrement ? ` INCREMENT BY ${identityIncrement}` : '';
const cache = numberToCache ? ` CACHE ${numberToCache}` : ' NOCACHE';
return `${startWith}${incrementBy}${cache}`;
};

return ` GENERATED${getGenerated(identity)} AS IDENTITY (${_.trim(getOptions(identity))})`;
} else if (defaultValue || defaultValue === 0) {
const onNull = defaultOnNull ? ' ON NULL' : '';

return ` DEFAULT${onNull} ${defaultValue}`;
}
return '';
};

const getColumnEncrypt = ({ encryption }) => {
if (_.isPlainObject(encryption) && !_.isEmpty(_.omit(encryption, 'id'))) {
const { ENCRYPTION_ALGORITHM, INTEGRITY_ALGORITHM, noSalt } = encryption;
Expand Down Expand Up @@ -219,23 +194,12 @@ module.exports = ({ _, wrap, assignTemplates, templates, commentIfDeactivated, w
return ` ${type}`;
};

/**
*
* @param {string} type
* @returns {boolean}
*/
const canHaveIdentity = type => {
const typesAllowedToHaveAutoIncrement = ['number'];
return typesAllowedToHaveAutoIncrement.includes(type);
};

return {
getColumnComments,
getColumnConstraints,
replaceTypeByVersion,
getColumnDefault,
getColumnEncrypt,
decorateType,
canHaveIdentity,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const { isEmpty, isNumber, trim } = require('lodash');

/**
* @enum
*/
const GENERATED_TYPE = {
always: 'ALWAYS',
byDefault: 'BY DEFAULT',
};

/**
* @typedef {{
* identityStart?: number;
* identityIncrement?: number;
* numberToCache?: number;
* }} Identity
*
* @typedef {{
* generatedType: GENERATED_TYPE | '';
* asIdentity?: boolean;
* generatedOnNull?: boolean;
* expression?: string;
* identity?: Identity;
* }} GeneratedDefaultValue
*/

/**
*
* @param {{ type: string; }}
* @returns {boolean}
*/
const canHaveIdentity = ({ type }) => {
const typesAllowedToHaveAutoIncrement = ['number'];
return typesAllowedToHaveAutoIncrement.includes(type.toLowerCase());
};

/**
* @param {{ onNull: boolean; }}
* @returns {string}
*/
const getOnNullClause = ({ onNull }) => (onNull ? ' ON NULL' : '');

/**
* @param {{ generatedType: string; generatedOnNull?: boolean; }}
* @returns {string}
*/
const getGeneratedClause = ({ generatedType, generatedOnNull }) => {
const onNull = getOnNullClause({ onNull: generatedOnNull });

switch (generatedType) {
case GENERATED_TYPE.byDefault: {
return ` GENERATED BY DEFAULT${onNull}`;
}
case GENERATED_TYPE.always: {
return ' GENERATED ALWAYS';
}
default: {
return '';
}
}
};

/**
* @param {{ identityStart?: number; identityIncrement?: number; numberToCache?: number; }}
* @returns {string}
*/
const getIdentityOptions = ({ identityStart, identityIncrement, numberToCache }) => {
const startWith = isNumber(identityStart) ? ` START WITH ${identityStart}` : '';
const incrementBy = isNumber(identityIncrement) ? ` INCREMENT BY ${identityIncrement}` : '';
const cache = isNumber(numberToCache) ? ` CACHE ${numberToCache}` : ' NOCACHE';

return trim(`${startWith}${incrementBy}${cache}`);
};

/**
* @param {{ type: string; default: any; defaultOnNull?: boolean; generatedDefaultValue?: GeneratedDefaultValue }}
* @returns {string}
*/
const getColumnDefault = ({ type, default: defaultValue, defaultOnNull, generatedDefaultValue = {} }) => {
const { generatedType, generatedOnNull, asIdentity, identity, expression } = generatedDefaultValue;
const generatedClause = getGeneratedClause({ generatedType, generatedOnNull });
const expressionValue = trim(expression);

if (generatedType && asIdentity && canHaveIdentity({ type }) && !isEmpty(identity)) {
const identityOptions = getIdentityOptions(identity);

return `${generatedClause} AS IDENTITY (${identityOptions})`;
}

if (expressionValue) {
return `${generatedClause} AS (${expressionValue})`;
}

if (defaultValue || defaultValue === 0) {
const onNull = getOnNullClause({ onNull: defaultOnNull });

return ` DEFAULT${onNull} ${defaultValue}`;
}

return '';
};

module.exports = {
getColumnDefault,
};
3 changes: 1 addition & 2 deletions forward_engineering/ddlProvider/ddlProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ module.exports = (baseProvider, options, app) => {
getColumnDefault,
getColumnEncrypt,
decorateType,
canHaveIdentity,
} = require('./ddlHelpers/columnDefinitionHelper.js')({
_,
wrap,
Expand Down Expand Up @@ -216,7 +215,7 @@ module.exports = (baseProvider, options, app) => {
dimension: jsonSchema.dimension,
subtype: jsonSchema.subtype,
defaultOnNull: jsonSchema.defaultOnNull,
...(canHaveIdentity(jsonSchema.mode) && { identity: jsonSchema.identity }),
generatedDefaultValue: jsonSchema.generatedDefaultValue,
};
},

Expand Down
29 changes: 27 additions & 2 deletions polyglot/adapter.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,38 @@
}
}
],
[
"movePropertyByPath",
{
"from": "identity",
"to": "generatedDefaultValue.identity"
}
],
[
"addMissingIdByPath",
{
"from": "generatedDefaultValue",
"path": "generatedDefaultValue.id"
}
],
[
"addPropertiesByPath",
[
{
"keyPath": "generatedDefaultValue",
"subProperties": {
"generatedType": "ALWAYS",
"asIdentity": true
}
}
]
],
[
"addPropertiesByPath",
[
{
"keyPath": "identity",
"keyPath": "generatedDefaultValue.identity",
"subProperties": {
"generated": "ALWAYS",
"numberToCache": 1
}
}
Expand Down
10 changes: 9 additions & 1 deletion polyglot/convertAdapter.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@
"mode": "integer"
}
},
[
"movePropertyByPath",
{
"from": "generatedDefaultValue.identity",
"to": "identity"
}
],
[
"removePropertiesByKeyPath",
[
Expand Down Expand Up @@ -107,5 +114,6 @@
}
]
}
}
},
"delete": ["generatedDefaultValue"]
}
Loading

0 comments on commit dcae3a8

Please sign in to comment.