From a714e114d56a619b876ddecec7c62d1142e37515 Mon Sep 17 00:00:00 2001 From: Yevhenii Moroziuk Date: Mon, 9 Feb 2026 14:09:03 +0200 Subject: [PATCH 1/4] HCK-14718: Include new properties of `AS IDENTITY` in the script (#86)
Sub-taskHCK-14718 FE: include new properties of `AS IDENTITY` in the script

--------- Co-authored-by: chulanovskyi --- .../columnDefinition/getColumnDefault.js | 5 +- .../field_level/fieldLevelConfig.json | 60 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/forward_engineering/ddlProvider/ddlHelpers/columnDefinition/getColumnDefault.js b/forward_engineering/ddlProvider/ddlHelpers/columnDefinition/getColumnDefault.js index 0589127..837d3d5 100644 --- a/forward_engineering/ddlProvider/ddlHelpers/columnDefinition/getColumnDefault.js +++ b/forward_engineering/ddlProvider/ddlHelpers/columnDefinition/getColumnDefault.js @@ -26,13 +26,14 @@ const isGeneratedAsIdentity = ({ identity, type }) => { * @param {{ start?: number, increment?: number, minValue?: number, maxValue?: number, cycle?: string }} param0 * @returns {string} */ -const getIdentityOptions = ({ start, increment, minValue, maxValue, cycle }) => { +const getIdentityOptions = ({ start, increment, minValue, maxValue, cycle, cache, cacheValue, order }) => { const startWith = start ? `START WITH ${start}` : ''; const incrementBy = increment ? `INCREMENT BY ${increment}` : ''; const minimumValue = minValue ? `MINVALUE ${minValue}` : ''; const maximumValue = maxValue ? `MAXVALUE ${maxValue}` : ''; + const cacheOption = cacheValue ? `CACHE ${cacheValue}` : cache; - return [startWith, incrementBy, cycle, minimumValue, maximumValue].filter(Boolean).join(', '); + return [startWith, incrementBy, cycle, minimumValue, maximumValue, cacheOption, order].filter(Boolean).join(', '); }; /** diff --git a/properties_pane/field_level/fieldLevelConfig.json b/properties_pane/field_level/fieldLevelConfig.json index 44f3c15..8335ae4 100644 --- a/properties_pane/field_level/fieldLevelConfig.json +++ b/properties_pane/field_level/fieldLevelConfig.json @@ -1016,7 +1016,6 @@ making sure that you maintain a proper JSON format. "value": "decimal" } }, - { "propertyName": "Default", "propertyKeyword": "default", @@ -1237,6 +1236,65 @@ making sure that you maintain a proper JSON format. ] } } + }, + { + "propertyName": "Cache", + "propertyKeyword": "cache", + "propertyTooltip": "Specify how many values of the sequence the database preallocates and keeps in memory for faster access. Specify NOCACHE to indicate that values of the sequence are not preallocated. If you omit both CACHE and NOCACHE, then the database caches 20 sequence numbers by default.", + "propertyType": "select", + "options": ["", "CACHE", "NO CACHE"], + "dependency": { + "type": "not", + "values": { + "type": "or", + "values": [ + { + "key": "generated", + "exist": false + }, + { + "key": "generated", + "value": "" + } + ] + } + } + }, + { + "propertyName": "Cache value", + "propertyKeyword": "cacheValue", + "propertyType": "numeric", + "valueType": "number", + "propertyTooltip": "This integer value can have 28 or fewer digits. The minimum value for this parameter is 2.", + "minValue": 2, + "defaultValue": 20, + "dependency": { + "key": "cache", + "value": "CACHE" + } + }, + { + "propertyName": "Order", + "propertyKeyword": "order", + "propertyTooltip": "Specify ORDER to guarantee that sequence numbers are generated in order of request. Specify NO ORDER if you do not want to guarantee sequence numbers are generated in order of request.", + "propertyType": "select", + "options": ["", "ORDER", "NO ORDER"], + "dependency": { + "type": "not", + "values": { + "type": "or", + "values": [ + { + "key": "generated", + "exist": false + }, + { + "key": "generated", + "value": "" + } + ] + } + } } ], "dependency": { From 712ef7b9184857654bf2030589a71e7bcf465ddf Mon Sep 17 00:00:00 2001 From: chulanovskyi-bs <56116665+chulanovskyi-bs@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:38:32 +0200 Subject: [PATCH 2/4] HCK-14717: DB2 RE from instance (#87)
Sub-taskHCK-14717 RE: extend grammar of `AS IDENTITY` clause

## Technical details * `CREATE TABLE` statements do not always appear as `OBJ_TYPE = 'TABLE'`. The approach is tranformed to filter by schema/table explicitly, adapting the query for view statements when specified exactly. --- constants/constants.js | 4 +-- reverse_engineering/api.js | 10 ++++---- shared/helpers/instanceHelper.js | 22 +++++++++++----- shared/helpers/queryHelper.js | 44 ++++++++++++++++++-------------- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/constants/constants.js b/constants/constants.js index c1d0a82..280731f 100644 --- a/constants/constants.js +++ b/constants/constants.js @@ -6,7 +6,7 @@ const ERROR_MESSAGE = { /** * @enum {string} */ -const TABLE_TYPE = { +const OBJECT_TYPE = { table: 'TABLE', view: 'VIEW', }; @@ -24,7 +24,7 @@ const CONSTRAINT_POSTFIX = { module.exports = { ERROR_MESSAGE, - TABLE_TYPE, + OBJECT_TYPE, INLINE_COMMENT, CONSTRAINT_POSTFIX, }; diff --git a/reverse_engineering/api.js b/reverse_engineering/api.js index 003f62d..5d53799 100644 --- a/reverse_engineering/api.js +++ b/reverse_engineering/api.js @@ -11,7 +11,7 @@ const { mapSeries } = require('async'); const { connectionHelper } = require('../shared/helpers/connectionHelper'); const { instanceHelper } = require('../shared/helpers/instanceHelper'); const { logHelper } = require('../shared/helpers/logHelper'); -const { TABLE_TYPE } = require('../constants/constants'); +const { OBJECT_TYPE } = require('../constants/constants'); const { nameHelper } = require('../shared/helpers/nameHelper'); const { testConnection } = require('../shared/api/testConnection'); @@ -83,7 +83,7 @@ const getDbCollectionsNames = async (connectionInfo, appLogger, callback, app) = const tableNames = await instanceHelper.getDatabasesWithTableNames({ connection, - tableType: TABLE_TYPE.table, + objectType: OBJECT_TYPE.table, includeSystemCollection: connectionInfo.includeSystemCollection, tableNameModifier: identity, }); @@ -92,7 +92,7 @@ const getDbCollectionsNames = async (connectionInfo, appLogger, callback, app) = const viewNames = await instanceHelper.getDatabasesWithTableNames({ connection, - tableType: TABLE_TYPE.view, + objectType: OBJECT_TYPE.view, includeSystemCollection: connectionInfo.includeSystemCollection, tableNameModifier: nameHelper.setViewSign, }); @@ -153,7 +153,7 @@ const getDbCollectionsData = async (connectionInfo, appLogger, callback, app) => connection, schemaName, tableName, - tableType: TABLE_TYPE.table, + objectType: OBJECT_TYPE.table, logger, }); @@ -185,7 +185,7 @@ const getDbCollectionsData = async (connectionInfo, appLogger, callback, app) => connection, schemaName, tableName: viewName, - tableType: TABLE_TYPE.view, + objectType: OBJECT_TYPE.view, logger, }); diff --git a/shared/helpers/instanceHelper.js b/shared/helpers/instanceHelper.js index 995b8db..65cf34c 100644 --- a/shared/helpers/instanceHelper.js +++ b/shared/helpers/instanceHelper.js @@ -4,7 +4,6 @@ * @typedef {import("../types").Logger} Logger */ -const { TABLE_TYPE } = require('../../constants/constants'); const { queryHelper } = require('./queryHelper'); /** @@ -32,11 +31,11 @@ const getSchemaNames = async ({ connection }) => { }; /** - * @param {{ connection: Connection, tableType: string, includeSystemCollection: boolean, tableNameModifier: (name: string) => string }} + * @param {{ connection: Connection, objectType: string, includeSystemCollection: boolean, tableNameModifier: (name: string) => string }} * @returns {Promise} */ -const getDatabasesWithTableNames = async ({ connection, tableType, includeSystemCollection, tableNameModifier }) => { - const query = queryHelper.getTableNamesQuery({ tableType, includeSystemCollection }); +const getDatabasesWithTableNames = async ({ connection, objectType, includeSystemCollection, tableNameModifier }) => { + const query = queryHelper.getTableNamesQuery({ objectType, includeSystemCollection }); const result = await connection.execute({ query }); return result.reduce((result, { SCHEMANAME, TABLENAME }) => { @@ -73,12 +72,21 @@ const getSchemaProperties = async ({ connection, schemaName, logger }) => { * @param {{ connection: Connection, schemaName: string, tableName: string, tableName: string, logger: Logger}} * @returns {Promise} */ -const getTableDdl = async ({ connection, schemaName, tableName, tableType, logger }) => { +const getTableDdl = async ({ connection, schemaName, tableName, objectType, logger }) => { try { - const generateQuery = queryHelper.getGenerateTableDdlQuery({ schemaName, tableName, tableType }); + const generateQuery = queryHelper.getGenerateTableDdlQuery({ schemaName, tableName, objectType }); + const opToken = await connection.execute({ query: generateQuery, callable: true }); - const selectQuery = queryHelper.getSelectTableDdlQuery({ opToken, tableType }); + + const selectQuery = queryHelper.getSelectTableDdlQuery({ + opToken, + schemaName, + objectName: tableName, + objectType, + }); + const ddlResult = await connection.execute({ query: selectQuery }); + const clearQuery = queryHelper.getClearTableDdlQuery(); await connection.execute({ query: clearQuery, callable: true, inparam: opToken }); diff --git a/shared/helpers/queryHelper.js b/shared/helpers/queryHelper.js index a65b788..b7de0a3 100644 --- a/shared/helpers/queryHelper.js +++ b/shared/helpers/queryHelper.js @@ -1,13 +1,13 @@ -const { TABLE_TYPE } = require('../../constants/constants'); +const { OBJECT_TYPE } = require('../../constants/constants'); /** - * @param {{ query: string }} + * @param {{ query: string }} params * @returns {string} */ const cleanUpQuery = ({ query = '' }) => query.replaceAll(/\s+/g, ' '); /** - * @param {{ query: string, schemaNameKeyword: string }} + * @param {{ query: string, schemaNameKeyword: string }} params * @returns {string} */ const getNonSystemSchemaWhereClause = ({ query, schemaNameKeyword }) => { @@ -43,7 +43,7 @@ const getSchemasQuery = () => { }; /** - * @param {{ schemaName: string }} + * @param {{ schemaName: string }} params * @returns {string} */ const getSchemaQuery = ({ schemaName }) => { @@ -51,11 +51,11 @@ const getSchemaQuery = ({ schemaName }) => { }; /** - * @param {{ tableType: string, includeSystemCollection: boolean }} + * @param {{ objectType: string, includeSystemCollection: boolean }} params * @returns {string} */ -const getTableNamesQuery = ({ tableType, includeSystemCollection }) => { - const baseQuery = `SELECT TABLE_SCHEM AS SCHEMANAME, TABLE_NAME AS TABLENAME FROM SYSIBM.SQLTABLES WHERE TABLE_TYPE = '${tableType}'`; +const getTableNamesQuery = ({ objectType, includeSystemCollection }) => { + const baseQuery = `SELECT TABLE_SCHEM AS SCHEMANAME, TABLE_NAME AS TABLENAME FROM SYSIBM.SQLTABLES WHERE TABLE_TYPE = '${objectType}'`; if (includeSystemCollection) { return baseQuery; @@ -67,27 +67,33 @@ const getTableNamesQuery = ({ tableType, includeSystemCollection }) => { }; /** - * @param {{ schemaName: string, tableName: string, tableType: string }} + * @param {{ schemaName: string, tableName: string, objectType: string }} params * @returns {string}; */ -const getGenerateTableDdlQuery = ({ schemaName, tableName, tableType }) => { - const tableArgument = tableType === TABLE_TYPE.table ? '-t' : '-v'; +const getGenerateTableDdlQuery = ({ schemaName, tableName, objectType }) => { + const objectArgument = objectType === OBJECT_TYPE.table ? '-t' : '-v'; - return `CALL SYSPROC.DB2LK_GENERATE_DDL('-a -e -z "${schemaName}" ${tableArgument} "${tableName}"', ?);`; + return `CALL SYSPROC.DB2LK_GENERATE_DDL('-a -e -z "${schemaName}" ${objectArgument} "${tableName}"', ?);`; }; /** - * @param {{ opToken: number, tableType: string }} + * @param {{ opToken: number, schemaName: string, objectName: string, objectType: string }} params * @returns {string} */ -const getSelectTableDdlQuery = ({ opToken, tableType }) => { - const objectTypeOperator = tableType === TABLE_TYPE.table ? '!=' : '='; +const getSelectTableDdlQuery = ({ opToken, schemaName, objectName, objectType }) => { + const predicate = + objectType === OBJECT_TYPE.view + ? `SQL_STMT LIKE 'CREATE%VIEW ${objectName}%' + OR SQL_STMT LIKE 'COMMENT ON TABLE ${objectName}%'` + : `SQL_STMT LIKE '%"${schemaName}"."${objectName}"%'`; + const query = ` - SELECT SQL_STMT - FROM SYSTOOLS.DB2LOOK_INFO - WHERE OP_TOKEN= ${opToken} - AND OBJ_TYPE ${objectTypeOperator} '${TABLE_TYPE.view}' - ORDER BY CREATION_TIME, OP_SEQUENCE;`; + SELECT SQL_STMT + FROM SYSTOOLS.DB2LOOK_INFO + WHERE OP_TOKEN = ${opToken} + AND ( ${predicate} ) + ORDER BY CREATION_TIME, OP_SEQUENCE + `; return cleanUpQuery({ query }); }; From 10667791ffad52a0ba5f7b478f19cdf5aab12f00 Mon Sep 17 00:00:00 2001 From: chulanovskyi-bs <56116665+chulanovskyi-bs@users.noreply.github.com> Date: Tue, 10 Feb 2026 17:14:13 +0200 Subject: [PATCH 3/4] HCK-14717: RE views (#88)
Sub-taskHCK-14717 RE: extend grammar of `AS IDENTITY` clause

## Technical details * lookup views by full path --- shared/helpers/instanceHelper.js | 2 +- shared/helpers/queryHelper.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/shared/helpers/instanceHelper.js b/shared/helpers/instanceHelper.js index 65cf34c..cb36248 100644 --- a/shared/helpers/instanceHelper.js +++ b/shared/helpers/instanceHelper.js @@ -91,7 +91,7 @@ const getTableDdl = async ({ connection, schemaName, tableName, objectType, logg await connection.execute({ query: clearQuery, callable: true, inparam: opToken }); - return ddlResult.map(row => row.SQL_STMT + ';').join('\n'); + return ddlResult.map(row => queryHelper.ensureTerminator({ query: row.SQL_STMT })).join('\n'); } catch (error) { logger.error(error); diff --git a/shared/helpers/queryHelper.js b/shared/helpers/queryHelper.js index b7de0a3..dd4f486 100644 --- a/shared/helpers/queryHelper.js +++ b/shared/helpers/queryHelper.js @@ -6,6 +6,8 @@ const { OBJECT_TYPE } = require('../../constants/constants'); */ const cleanUpQuery = ({ query = '' }) => query.replaceAll(/\s+/g, ' '); +const ensureTerminator = ({ query = '' }) => (query.trimEnd().endsWith(';') ? query : `${query};`); + /** * @param {{ query: string, schemaNameKeyword: string }} params * @returns {string} @@ -83,9 +85,9 @@ const getGenerateTableDdlQuery = ({ schemaName, tableName, objectType }) => { const getSelectTableDdlQuery = ({ opToken, schemaName, objectName, objectType }) => { const predicate = objectType === OBJECT_TYPE.view - ? `SQL_STMT LIKE 'CREATE%VIEW ${objectName}%' - OR SQL_STMT LIKE 'COMMENT ON TABLE ${objectName}%'` - : `SQL_STMT LIKE '%"${schemaName}"."${objectName}"%'`; + ? `SQL_STMT LIKE 'CREATE%VIEW %"${schemaName}%"."${objectName}"%' + OR SQL_STMT LIKE 'COMMENT ON TABLE %"${schemaName}%"."${objectName}"%'` + : `SQL_STMT LIKE '%"${schemaName}%"."${objectName}"%'`; const query = ` SELECT SQL_STMT @@ -114,6 +116,7 @@ const queryHelper = { getGenerateTableDdlQuery, getSelectTableDdlQuery, getClearTableDdlQuery, + ensureTerminator, }; module.exports = { From e07929b272dffbc3e48f820e10cd3f2afebe7e3f Mon Sep 17 00:00:00 2001 From: chulanovskyi Date: Tue, 10 Feb 2026 18:03:30 +0200 Subject: [PATCH 4/4] fix: allow view names without double quotes --- shared/helpers/queryHelper.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/helpers/queryHelper.js b/shared/helpers/queryHelper.js index dd4f486..656ab34 100644 --- a/shared/helpers/queryHelper.js +++ b/shared/helpers/queryHelper.js @@ -86,6 +86,8 @@ const getSelectTableDdlQuery = ({ opToken, schemaName, objectName, objectType }) const predicate = objectType === OBJECT_TYPE.view ? `SQL_STMT LIKE 'CREATE%VIEW %"${schemaName}%"."${objectName}"%' + OR SQL_STMT LIKE 'CREATE%VIEW "${objectName}"%' + OR SQL_STMT LIKE 'CREATE%VIEW ${objectName}%' OR SQL_STMT LIKE 'COMMENT ON TABLE %"${schemaName}%"."${objectName}"%'` : `SQL_STMT LIKE '%"${schemaName}%"."${objectName}"%'`;