diff --git a/localization/en.json b/localization/en.json index 76327b7..a253c7a 100644 --- a/localization/en.json +++ b/localization/en.json @@ -79,7 +79,6 @@ "MODAL_WINDOW___SUBDOCUMENT_IN_CHILD": "Sub-document in child", "MODAL_WINDOW___ARRAY_IN_PARENT": "Array in parent", "MODAL_WINDOW___INCLUDE_EMPTY_COLLECTION": "Include empty tables", - "MODAL_WINDOW___INCLUDE_PROCEDURES": "Include stored procedures", "MODAL_WINDOW___CREATE_COLLECTION": "Create table", "MODAL_WINDOW___CREATE_BUCKET": "Create schema", "MODAL_WINDOW___ALL_COLLECTIONS": "and all nested tables", diff --git a/reverse_engineering/config.json b/reverse_engineering/config.json index 983d9c5..3d34e74 100644 --- a/reverse_engineering/config.json +++ b/reverse_engineering/config.json @@ -16,5 +16,12 @@ } ], "externalBrowserPort": 8080, - "helpUrl": "https://hackolade.com/help/ConnecttoaSQLServerinstance.html" + "helpUrl": "https://hackolade.com/help/ConnecttoaSQLServerinstance.html", + "options": [ + { + "inputLabel": "Include stored procedures", + "inputTooltip": "Reverse-engineer stored procedures", + "inputKeyword": "includeProcedures" + } + ] } diff --git a/reverse_engineering/databaseService/databaseService.js b/reverse_engineering/databaseService/databaseService.js index afb97a5..a51186b 100644 --- a/reverse_engineering/databaseService/databaseService.js +++ b/reverse_engineering/databaseService/databaseService.js @@ -1001,7 +1001,7 @@ const getWhereClauseForUniqueSchemasAndTables = ({ tableAlias, allUniqueSchemasA `OBJECT_SCHEMA_NAME(${tableAlias}.object_id) IN (${[...schemas].join(', ')}) AND OBJECT_NAME(${tableAlias}.object_id) IN (${[...tables].join(', ')})`; -const getDatabaseProcedures = async ({ client, dbName, logger, includeProcedures }) => { +const getDatabaseProcedures = async ({ client, dbName, logger, includeProcedures, allUniqueSchemasAndTables }) => { if (!includeProcedures) { logger.log( 'info', @@ -1021,17 +1021,25 @@ const getDatabaseProcedures = async ({ client, dbName, logger, includeProcedures dbName, meta: { action: 'getting procedures query', - objects: ['sys.procedures', 'sys.schemas', 'sys.sql_modules', 'sys.extended_properties'], + objects: [ + 'sys.procedures', + 'sys.schemas', + 'sys.sql_modules', + 'sys.extended_properties', + 'sys.sql_expression_dependencies', + ], skip: true, }, logger, }); + const { schemas, tables } = allUniqueSchemasAndTables; + logger.log('info', { message: `Get '${dbName}' database procedures.` }, 'Reverse Engineering'); logger.progress({ message: 'Discovering stored procedure metadata', containerName: dbName, entityName: '' }); const response = await currentDbConnectionClient.query(` - SELECT + SELECT DISTINCT s.name AS schema_name, p.name AS procedure_name, sm.definition AS procedure_body, @@ -1045,12 +1053,20 @@ const getDatabaseProcedures = async ({ client, dbName, logger, includeProcedures ON ep.major_id = p.object_id AND ep.minor_id = 0 AND ep.name = 'MS_Description' - ORDER BY s.name, p.name; + INNER JOIN sys.sql_expression_dependencies sed + ON p.object_id = sed.referencing_id + WHERE s.name IN (${[...schemas].join(', ')}) + AND sed.referenced_entity_name IN (${[...tables].join(', ')}) + ORDER BY s.name, p.name `); const rawProcedures = await mapResponse(response); - logger.log('info', { message: `Parsing procedures.` }, 'Reverse Engineering'); + logger.log( + 'info', + { message: `Fetching stored procedures completed. Procedures found: ${rawProcedures.length}.` }, + 'Reverse Engineering', + ); logger.progress({ message: 'Parsing procedures', containerName: dbName, entityName: '' }); const start = Date.now(); const parsedProcedures = rawProcedures.map(parseProcedure(logger)); diff --git a/reverse_engineering/reverseEngineeringService/reverseEngineeringService.js b/reverse_engineering/reverseEngineeringService/reverseEngineeringService.js index 1663d1b..6584940 100644 --- a/reverse_engineering/reverseEngineeringService/reverseEngineeringService.js +++ b/reverse_engineering/reverseEngineeringService/reverseEngineeringService.js @@ -323,7 +323,13 @@ const fetchDatabaseMetadata = async ({ client, dbName, tablesInfo, logger, rever }); logDiscoveredMetadataCount({ logger, label: 'spatial indexes', items: spatialIndexes }); - const procedures = await getDatabaseProcedures({ client, dbName, logger, includeProcedures }); + const procedures = await getDatabaseProcedures({ + client, + dbName, + logger, + includeProcedures, + allUniqueSchemasAndTables, + }); const indexesBucketCount = await getIndexesBucketCount({ client,