From 2b2ecac3ab9514b179d03d9ef541c3126a0da89d Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 26 Nov 2024 17:05:12 +0100 Subject: [PATCH 01/38] feat: stored procedures and funciton parameters support for mssql --- packages/types/dbinfo.d.ts | 18 +++++- .../web/src/appobj/AppObjectListItem.svelte | 2 +- .../web/src/appobj/ParameterAppObject.svelte | 18 ++++++ .../src/appobj/SubProcedureParamList.svelte | 15 +++++ packages/web/src/icons/FontIcon.svelte | 1 + .../web/src/widgets/ConnectionList.svelte | 4 +- packages/web/src/widgets/SqlObjectList.svelte | 12 +++- .../src/backend/MsSqlAnalyser.js | 55 ++++++++++++++++--- .../src/backend/sql/functionParameters.js | 26 +++++++++ .../src/backend/sql/index.js | 4 ++ .../src/backend/sql/proceduresParameters.js | 21 +++++++ 11 files changed, 162 insertions(+), 14 deletions(-) create mode 100644 packages/web/src/appobj/ParameterAppObject.svelte create mode 100644 packages/web/src/appobj/SubProcedureParamList.svelte create mode 100644 plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js create mode 100644 plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index b5b59d1ec..680bbb236 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -35,7 +35,7 @@ export interface IndexInfo extends ColumnsConstraintInfo { isUnique: boolean; // indexType: 'normal' | 'clustered' | 'xml' | 'spatial' | 'fulltext'; indexType?: string; - // condition for filtered index (SQL Server) + // condition for filtered index (SQL Server) filterDefinition?: string; } @@ -118,9 +118,23 @@ export interface ViewInfo extends SqlObjectInfo { columns: ColumnInfo[]; } -export interface ProcedureInfo extends SqlObjectInfo {} +export interface ParameterInfo { + objectId?: string | number; + parentObjectId?: string | number; + pureName: string; + dataType: string; + fullDataType: string; + maxLength?: number; + precision?: number; + scale?: string; + isOutputParameter?: boolean; +} +export interface ProcedureInfo extends SqlObjectInfo { + parameters?: ParameterInfo[]; +} export interface FunctionInfo extends SqlObjectInfo { + parameters?: ParameterInfo[]; // returnDataType?: string; } diff --git a/packages/web/src/appobj/AppObjectListItem.svelte b/packages/web/src/appobj/AppObjectListItem.svelte index 2b61b232b..395127e63 100644 --- a/packages/web/src/appobj/AppObjectListItem.svelte +++ b/packages/web/src/appobj/AppObjectListItem.svelte @@ -62,7 +62,7 @@ {#if (isExpanded || isExpandedBySearch) && subItemsComponent}
+ export const extractKey = ({ columnName }) => columnName; + + + + + diff --git a/packages/web/src/appobj/SubProcedureParamList.svelte b/packages/web/src/appobj/SubProcedureParamList.svelte new file mode 100644 index 000000000..206321594 --- /dev/null +++ b/packages/web/src/appobj/SubProcedureParamList.svelte @@ -0,0 +1,15 @@ + + + ({ + ...data, + ...parameter, + }))} + module={parameterAppObject} +/> diff --git a/packages/web/src/icons/FontIcon.svelte b/packages/web/src/icons/FontIcon.svelte index 90cdae967..1f8d6930f 100644 --- a/packages/web/src/icons/FontIcon.svelte +++ b/packages/web/src/icons/FontIcon.svelte @@ -63,6 +63,7 @@ 'icon open-in-new': 'mdi mdi-open-in-new', 'icon add-folder': 'mdi mdi-folder-plus-outline', 'icon add-column': 'mdi mdi-table-column-plus-after', + 'icon parameter': 'mdi mdi-at', 'icon window-restore': 'mdi mdi-window-restore', 'icon window-maximize': 'mdi mdi-window-maximize', diff --git a/packages/web/src/widgets/ConnectionList.svelte b/packages/web/src/widgets/ConnectionList.svelte index 4b84fe07d..61ba93bc3 100644 --- a/packages/web/src/widgets/ConnectionList.svelte +++ b/packages/web/src/widgets/ConnectionList.svelte @@ -251,7 +251,7 @@ SubDatabaseList} expandOnClick isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase} {filter} @@ -275,7 +275,7 @@ SubDatabaseList} expandOnClick isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase} {filter} diff --git a/packages/web/src/widgets/SqlObjectList.svelte b/packages/web/src/widgets/SqlObjectList.svelte index a71d4cbc4..04151597b 100644 --- a/packages/web/src/widgets/SqlObjectList.svelte +++ b/packages/web/src/widgets/SqlObjectList.svelte @@ -52,6 +52,7 @@ import AppObjectListHandler from './AppObjectListHandler.svelte'; import { matchDatabaseObjectAppObject } from '../appobj/appObjectTools'; import FocusedConnectionInfoWidget from './FocusedConnectionInfoWidget.svelte'; + import SubProcedureParamList from '../appobj/SubProcedureParamList.svelte'; export let conid; export let database; @@ -232,9 +233,16 @@ .map(x => ({ ...x, conid, database }))} module={databaseObjectAppObject} groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField, driver)} - subItemsComponent={SubColumnParamList} + subItemsComponent={data => + data.objectTypeField == 'procedures' || data.objectTypeField == 'functions' + ? SubProcedureParamList + : SubColumnParamList} isExpandable={data => - data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'} + data.objectTypeField == 'tables' || + data.objectTypeField == 'views' || + data.objectTypeField == 'matviews' || + ((data.objectTypeField == 'procedures' || data.objectTypeField == 'functions') && + !!data.parameters?.length)} expandIconFunc={chevronExpandIcon} {filter} passProps={{ diff --git a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js index 1eac0ea32..72b4060f9 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js +++ b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js @@ -31,6 +31,18 @@ function simplifyComutedExpression(expr) { return expr; } +function getFullDataTypeName({ dataType, charMaxLength, numericScale, numericPrecision }) { + let fullDataType = dataType; + if (charMaxLength && isTypeString(dataType)) { + fullDataType = `${dataType}(${charMaxLength < 0 ? 'MAX' : charMaxLength})`; + } + if (numericPrecision && numericScale && isTypeNumeric(dataType)) { + fullDataType = `${dataType}(${numericPrecision},${numericScale})`; + } + + return fullDataType; +} + function getColumnInfo({ isNullable, isIdentity, @@ -43,13 +55,12 @@ function getColumnInfo({ defaultConstraint, computedExpression, }) { - let fullDataType = dataType; - if (charMaxLength && isTypeString(dataType)) { - fullDataType = `${dataType}(${charMaxLength < 0 ? 'MAX' : charMaxLength})`; - } - if (numericPrecision && numericScale && isTypeNumeric(dataType)) { - fullDataType = `${dataType}(${numericPrecision},${numericScale})`; - } + const fullDataType = getFullDataTypeName({ + dataType, + charMaxLength, + numericPrecision, + numericScale, + }); if (defaultValue) { defaultValue = defaultValue.trim(); @@ -116,7 +127,11 @@ class MsSqlAnalyser extends DatabaseAnalyser { this.feedback({ analysingMessage: 'Loading views' }); const viewsRows = await this.analyserQuery('views', ['views']); this.feedback({ analysingMessage: 'Loading procedures & functions' }); + const programmableRows = await this.analyserQuery('programmables', ['procedures', 'functions']); + const prodceureParameterRows = await this.analyserQuery('proceduresParameters'); + const functionParameterRows = await this.analyserQuery('functionParameters'); + this.feedback({ analysingMessage: 'Loading view columns' }); const viewColumnRows = await this.analyserQuery('viewColumns', ['views']); @@ -157,20 +172,46 @@ class MsSqlAnalyser extends DatabaseAnalyser { columns: viewColumnRows.rows.filter(col => col.objectId == row.objectId).map(getColumnInfo), })); + const prodceureParameter = prodceureParameterRows.rows.map(row => ({ + ...row, + fullDataType: getFullDataTypeName(row), + })); + + const prodceureToParameters = prodceureParameter.reduce((acc, parameter) => { + if (!acc[parameter.parentObjectId]) acc[parameter.parentObjectId] = []; + acc[parameter.parentObjectId].push(parameter); + + return acc; + }, {}); + const procedures = programmableRows.rows .filter(x => x.sqlObjectType.trim() == 'P') .map(row => ({ ...row, contentHash: row.modifyDate && row.modifyDate.toISOString(), createSql: getCreateSql(row), + parameters: prodceureToParameters[row.objectId], })); + const functionParameters = functionParameterRows.rows.map(row => ({ + ...row, + fullDataType: getFullDataTypeName(row), + })); + + const functionToParameters = functionParameters.reduce((acc, parameter) => { + if (!acc[parameter.parentObjectId]) acc[parameter.parentObjectId] = []; + + acc[parameter.parentObjectId].push(parameter); + return acc; + }, {}); + const functions = programmableRows.rows .filter(x => ['FN', 'IF', 'TF'].includes(x.sqlObjectType.trim())) .map(row => ({ ...row, contentHash: row.modifyDate && row.modifyDate.toISOString(), createSql: getCreateSql(row), + parameters: functionToParameters[row.objectId], })); this.feedback({ analysingMessage: null }); diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js new file mode 100644 index 000000000..f7b40dc72 --- /dev/null +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js @@ -0,0 +1,26 @@ +module.exports = ` +SELECT + o.object_id as parentObjectId, + p.object_id AS parameterObjectId, + CASE + WHEN p.name IS NULL OR LTRIM(RTRIM(p.name)) = '' THEN + '@Output' + ELSE + p.name + END AS pureName, + TYPE_NAME(p.user_type_id) AS dataType, + p.max_length AS charMaxLength, + p.precision AS precision, + p.scale AS scale, + p.is_output AS isOutputParameter, + p.parameter_id AS parameterIndex +FROM + sys.objects o +JOIN + sys.parameters p ON o.object_id = p.object_id +WHERE + o.type IN ('FN', 'IF', 'TF') +ORDER BY + p.object_id, + p.parameter_id; +`; diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/index.js b/plugins/dbgate-plugin-mssql/src/backend/sql/index.js index 563b8d080..6352b6a9b 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/index.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/index.js @@ -7,6 +7,8 @@ const modifications = require('./modifications'); const loadSqlCode = require('./loadSqlCode'); const views = require('./views'); const programmables = require('./programmables'); +const proceduresParameters = require('./proceduresParameters'); +const functionParameters = require('./functionParameters'); const viewColumns = require('./viewColumns'); const indexes = require('./indexes'); const indexcols = require('./indexcols'); @@ -20,6 +22,8 @@ module.exports = { loadSqlCode, views, programmables, + proceduresParameters, + functionParameters, viewColumns, indexes, indexcols, diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js new file mode 100644 index 000000000..00c7b2c9f --- /dev/null +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -0,0 +1,21 @@ +module.exports = ` +SELECT + o.object_id as parentObjectId, + p.object_id as objectId, + p.name AS pureName, + TYPE_NAME(p.user_type_id) AS dataType, + p.max_length AS charMaxLength, + p.precision AS precision, + p.scale AS scale, + p.is_output AS isOutputParameter, + p.parameter_id AS parameterIndex +FROM + sys.objects o +JOIN + sys.parameters p ON o.object_id = p.object_id +WHERE + o.type = 'P' +ORDER BY + o.object_id, + p.parameter_id; +`; From 6b155083efdb99724bd7b9be4f4fe751ebd29727 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Wed, 27 Nov 2024 10:08:17 +0100 Subject: [PATCH 02/38] feat: stored procedures and funciton parameters support for pssql --- packages/types/dbinfo.d.ts | 1 + .../src/backend/Analyser.js | 40 +++++++++++++++++++ .../src/backend/sql/index.js | 2 + .../src/backend/sql/proceduresParameters.js | 27 +++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 680bbb236..1b9776a12 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -121,6 +121,7 @@ export interface ViewInfo extends SqlObjectInfo { export interface ParameterInfo { objectId?: string | number; parentObjectId?: string | number; + routineName?: string; pureName: string; dataType: string; fullDataType: string; diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 84b67a858..a7633fc61 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -144,6 +144,8 @@ class Analyser extends DatabaseAnalyser { this.feedback({ analysingMessage: 'Loading routines' }); const routines = await this.analyserQuery('routines', ['procedures', 'functions']); + const routineParametersRows = await this.analyserQuery('proceduresParameters'); + this.feedback({ analysingMessage: 'Loading indexes' }); const indexes = this.driver.__analyserInternals.skipIndexes ? { rows: [] } @@ -191,6 +193,42 @@ class Analyser extends DatabaseAnalyser { columnName: x.column_name, })); + const procedurePerameters = routineParametersRows.rows + .filter(i => i.routine_type == 'PROCEDURE') + .map(i => ({ + objectId: 'procedures:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, + routineName: i.routine_name, + pureName: i.pure_name, + dataType: i.data_type, + fullDataType: i.data_type, + isOutputParameter: i.is_output_parameter, + })); + + const procedureNameToParameters = procedurePerameters.reduce((acc, row) => { + if (!acc[row.routineName]) acc[row.routineName] = []; + acc[row.routineName].push(row); + + return acc; + }, {}); + + const fucntionPerameters = routineParametersRows.rows + .filter(i => i.routine_type == 'FUNCTION') + .map(i => ({ + objectId: 'functions:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, + routineName: i.routine_name, + pureName: i.pure_name, + dataType: i.data_type, + fullDataType: i.data_type, + isOutputParameter: i.is_output_parameter, + })); + + const functionNameToParameters = fucntionPerameters.reduce((acc, row) => { + if (!acc[row.routineName]) acc[row.routineName] = []; + acc[row.routineName].push(row); + + return acc; + }, {}); + const res = { tables: tables.rows.map(table => { const newTable = { @@ -281,6 +319,7 @@ class Analyser extends DatabaseAnalyser { schemaName: proc.schema_name, createSql: `CREATE PROCEDURE "${proc.schema_name}"."${proc.pure_name}"() LANGUAGE ${proc.language}\nAS\n$$\n${proc.definition}\n$$`, contentHash: proc.hash_code, + parameters: procedureNameToParameters[proc.pure_name], })), functions: routines.rows .filter(x => x.object_type == 'FUNCTION') @@ -290,6 +329,7 @@ class Analyser extends DatabaseAnalyser { pureName: func.pure_name, schemaName: func.schema_name, contentHash: func.hash_code, + parameters: functionNameToParameters[func.pure_name], })), }; diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/index.js b/plugins/dbgate-plugin-postgres/src/backend/sql/index.js index 53a858ab5..b3f338646 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/index.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/index.js @@ -14,6 +14,7 @@ const indexcols = require('./indexcols'); const uniqueNames = require('./uniqueNames'); const geometryColumns = require('./geometryColumns'); const geographyColumns = require('./geographyColumns'); +const proceduresParameters = require('./proceduresParameters'); const fk_keyColumnUsage = require('./fk_key_column_usage'); const fk_referentialConstraints = require('./fk_referential_constraints'); @@ -39,4 +40,5 @@ module.exports = { uniqueNames, geometryColumns, geographyColumns, + proceduresParameters, }; diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js new file mode 100644 index 000000000..7a275e6e9 --- /dev/null +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -0,0 +1,27 @@ +module.exports = ` +SELECT + proc.specific_schema AS specific_schema, + proc.routine_name AS routine_name, + proc.routine_type as routine_type, + args.parameter_name AS pure_name, + args.parameter_mode, + args.data_type AS data_type, + args.ordinal_position AS parameter_index, + CASE + WHEN args.parameter_mode IN ('OUT', 'INOUT') THEN TRUE + ELSE FALSE + END AS is_output_paramter +FROM + information_schema.routines proc +LEFT JOIN + information_schema.parameters args + ON proc.specific_schema = args.specific_schema + AND proc.specific_name = args.specific_name +WHERE + proc.routine_schema NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas + AND proc.routine_type IN ('PROCEDURE', 'FUNCTION') -- Filter for procedures +ORDER BY + specific_schema, + routine_name, + args.ordinal_position; +`; From 926949dc89d9752323e91f044851b9620dc0d6c3 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 09:57:59 +0100 Subject: [PATCH 03/38] fix: remove redundant field from ParameterInfo --- packages/types/dbinfo.d.ts | 8 ++----- .../web/src/appobj/ParameterAppObject.svelte | 4 ++-- .../src/backend/Analyser.js | 22 ++++++++++--------- .../src/backend/sql/proceduresParameters.js | 13 ++++++----- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 1b9776a12..890de2368 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -120,14 +120,10 @@ export interface ViewInfo extends SqlObjectInfo { export interface ParameterInfo { objectId?: string | number; - parentObjectId?: string | number; - routineName?: string; + schemaName: string; + parameterName?: string; pureName: string; dataType: string; - fullDataType: string; - maxLength?: number; - precision?: number; - scale?: string; isOutputParameter?: boolean; } export interface ProcedureInfo extends SqlObjectInfo { diff --git a/packages/web/src/appobj/ParameterAppObject.svelte b/packages/web/src/appobj/ParameterAppObject.svelte index 1ad9d3618..adc875aea 100644 --- a/packages/web/src/appobj/ParameterAppObject.svelte +++ b/packages/web/src/appobj/ParameterAppObject.svelte @@ -11,8 +11,8 @@ diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index a7633fc61..3f1cfb509 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -197,34 +197,36 @@ class Analyser extends DatabaseAnalyser { .filter(i => i.routine_type == 'PROCEDURE') .map(i => ({ objectId: 'procedures:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, - routineName: i.routine_name, pureName: i.pure_name, + parameterName: i.parameter_name, dataType: i.data_type, - fullDataType: i.data_type, isOutputParameter: i.is_output_parameter, + parameterMode: i.parameter_mode, + schemaName: i.schema_name, })); const procedureNameToParameters = procedurePerameters.reduce((acc, row) => { - if (!acc[row.routineName]) acc[row.routineName] = []; - acc[row.routineName].push(row); + if (!acc[row.pureName]) acc[row.pureName] = []; + acc[row.pureName].push(row); return acc; }, {}); - const fucntionPerameters = routineParametersRows.rows + const functionParameters = routineParametersRows.rows .filter(i => i.routine_type == 'FUNCTION') .map(i => ({ objectId: 'functions:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, - routineName: i.routine_name, pureName: i.pure_name, + parameterName: i.parameter_name, dataType: i.data_type, - fullDataType: i.data_type, isOutputParameter: i.is_output_parameter, + parameterMode: i.parameter_mode, + schemaName: i.schema_name, })); - const functionNameToParameters = fucntionPerameters.reduce((acc, row) => { - if (!acc[row.routineName]) acc[row.routineName] = []; - acc[row.routineName].push(row); + const functionNameToParameters = functionParameters.reduce((acc, row) => { + if (!acc[row.pureName]) acc[row.pureName] = []; + acc[row.pureName].push(row); return acc; }, {}); diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js index 7a275e6e9..c128d73f5 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -1,16 +1,17 @@ module.exports = ` SELECT - proc.specific_schema AS specific_schema, - proc.routine_name AS routine_name, + proc.specific_schema AS schema_name, + proc.routine_name AS pure_name, proc.routine_type as routine_type, - args.parameter_name AS pure_name, + args.parameter_name AS parameter_name, args.parameter_mode, args.data_type AS data_type, args.ordinal_position AS parameter_index, + args.parameter_mode AS parameter_mode, CASE WHEN args.parameter_mode IN ('OUT', 'INOUT') THEN TRUE ELSE FALSE - END AS is_output_paramter + END AS is_output_parameter FROM information_schema.routines proc LEFT JOIN @@ -21,7 +22,7 @@ WHERE proc.routine_schema NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas AND proc.routine_type IN ('PROCEDURE', 'FUNCTION') -- Filter for procedures ORDER BY - specific_schema, - routine_name, + schema_name, + parameter_name, args.ordinal_position; `; From 3a126011039688bfab56b2169505338242406f02 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 09:58:11 +0100 Subject: [PATCH 04/38] feat: add parameters to createSql for pssql --- .../dbgate-plugin-postgres/src/backend/Analyser.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 3f1cfb509..87a899a59 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -49,6 +49,12 @@ function getColumnInfo( }; } +function getParametersSqlString(parameters = []) { + if (!parameters?.length) return ''; + + return parameters.map(i => `${i.parameterMode} ${i.parameterName} ${i.dataType.toUpperCase()}`).join(', '); +} + class Analyser extends DatabaseAnalyser { constructor(dbhan, driver, version) { super(dbhan, driver, version); @@ -319,7 +325,9 @@ class Analyser extends DatabaseAnalyser { objectId: `procedures:${proc.schema_name}.${proc.pure_name}`, pureName: proc.pure_name, schemaName: proc.schema_name, - createSql: `CREATE PROCEDURE "${proc.schema_name}"."${proc.pure_name}"() LANGUAGE ${proc.language}\nAS\n$$\n${proc.definition}\n$$`, + createSql: `CREATE PROCEDURE "${proc.schema_name}"."${proc.pure_name}"(${getParametersSqlString( + procedureNameToParameters[proc.pure_name] + )}) LANGUAGE ${proc.language}\nAS\n$$\n${proc.definition}\n$$`, contentHash: proc.hash_code, parameters: procedureNameToParameters[proc.pure_name], })), @@ -327,7 +335,9 @@ class Analyser extends DatabaseAnalyser { .filter(x => x.object_type == 'FUNCTION') .map(func => ({ objectId: `functions:${func.schema_name}.${func.pure_name}`, - createSql: `CREATE FUNCTION "${func.schema_name}"."${func.pure_name}"() RETURNS ${func.data_type} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`, + createSql: `CREATE FUNCTION "${func.schema_name}"."${func.pure_name}"(${getParametersSqlString( + functionNameToParameters[func.pure_name] + )}) RETURNS ${func.data_type} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`, pureName: func.pure_name, schemaName: func.schema_name, contentHash: func.hash_code, From 8313d7f9f17f1fcbae2328795c27fd9bc0d8c5b8 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 10:03:16 +0100 Subject: [PATCH 05/38] fix: update mssql parameters query to match ParameterInfo --- .../dbgate-plugin-mssql/src/backend/sql/functionParameters.js | 3 ++- .../src/backend/sql/proceduresParameters.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js index f7b40dc72..75e94af53 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js @@ -2,12 +2,13 @@ module.exports = ` SELECT o.object_id as parentObjectId, p.object_id AS parameterObjectId, + o.name as pureName, CASE WHEN p.name IS NULL OR LTRIM(RTRIM(p.name)) = '' THEN '@Output' ELSE p.name - END AS pureName, + END AS parameterName, TYPE_NAME(p.user_type_id) AS dataType, p.max_length AS charMaxLength, p.precision AS precision, diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index 00c7b2c9f..b7be370cd 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -2,7 +2,8 @@ module.exports = ` SELECT o.object_id as parentObjectId, p.object_id as objectId, - p.name AS pureName, + o.name as pureName, + p.name AS parameterName, TYPE_NAME(p.user_type_id) AS dataType, p.max_length AS charMaxLength, p.precision AS precision, From fcd6f6c8fc06adae3066dc4eb539e0a1ece3dc19 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 10:58:13 +0100 Subject: [PATCH 06/38] fix: correcttly map parameters to object list --- packages/web/src/appobj/SubProcedureParamList.svelte | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/web/src/appobj/SubProcedureParamList.svelte b/packages/web/src/appobj/SubProcedureParamList.svelte index 206321594..852775e26 100644 --- a/packages/web/src/appobj/SubProcedureParamList.svelte +++ b/packages/web/src/appobj/SubProcedureParamList.svelte @@ -6,10 +6,9 @@ ({ - ...data, - ...parameter, - }))} + list={(data.parameters || []).map(parameter => ({ + ...data, + ...parameter, + }))} module={parameterAppObject} /> From a89d2e13653ac6aa68dd75e5093e7526edb36232 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 10:58:37 +0100 Subject: [PATCH 07/38] fix: add missing conditions for mssql parameters queries --- .../src/backend/sql/functionParameters.js | 6 +++++- .../src/backend/sql/proceduresParameters.js | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js index 75e94af53..1d1d98297 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js @@ -14,13 +14,17 @@ SELECT p.precision AS precision, p.scale AS scale, p.is_output AS isOutputParameter, - p.parameter_id AS parameterIndex + p.parameter_id AS parameterIndex, + s.name as schemaName FROM sys.objects o JOIN sys.parameters p ON o.object_id = p.object_id +INNER JOIN + sys.schemas s ON s.schema_id=o.schema_id WHERE o.type IN ('FN', 'IF', 'TF') + and o.object_id =OBJECT_ID_CONDITION and s.name =SCHEMA_NAME_CONDITION ORDER BY p.object_id, p.parameter_id; diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index b7be370cd..14fe6c96a 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -10,12 +10,16 @@ SELECT p.scale AS scale, p.is_output AS isOutputParameter, p.parameter_id AS parameterIndex + s.name as schemaName FROM sys.objects o JOIN sys.parameters p ON o.object_id = p.object_id +INNER JOIN + sys.schemas s ON s.schema_id=o.schema_id WHERE o.type = 'P' + and o.object_id =OBJECT_ID_CONDITION and s.name =SCHEMA_NAME_CONDITION ORDER BY o.object_id, p.parameter_id; From 7f9a30f568c3dccbd849f3ada0aed4f3a1f5be25 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 11:37:47 +0100 Subject: [PATCH 08/38] fix: add missing conditions for pssql parameters query --- .../src/backend/sql/proceduresParameters.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js index c128d73f5..1e37d3f2a 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -13,14 +13,21 @@ SELECT ELSE FALSE END AS is_output_parameter FROM - information_schema.routines proc + information_schema.routines proc LEFT JOIN information_schema.parameters args ON proc.specific_schema = args.specific_schema AND proc.specific_name = args.specific_name WHERE - proc.routine_schema NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas + proc.specific_schema NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas AND proc.routine_type IN ('PROCEDURE', 'FUNCTION') -- Filter for procedures + AND proc.specific_schema !~ '^_timescaledb_' + AND proc.specific_schema =SCHEMA_NAME_CONDITION + AND ( + (routine_type = 'PROCEDURE' AND ('procedures:' || proc.specific_schema || '.' || routine_name) =OBJECT_ID_CONDITION) + OR + (routine_type = 'FUNCTION' AND ('functions:' || proc.specific_schema || '.' || routine_name) =OBJECT_ID_CONDITION) + ) ORDER BY schema_name, parameter_name, From 262b4732e3c96f792d4a6b65cd68f806c83866b8 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 13:16:30 +0100 Subject: [PATCH 09/38] feat: use parameterMode instead of isOutputParameter --- packages/types/dbinfo.d.ts | 4 +++- packages/web/src/appobj/ParameterAppObject.svelte | 2 +- .../src/backend/sql/functionParameters.js | 5 ++++- .../src/backend/sql/proceduresParameters.js | 5 ++++- plugins/dbgate-plugin-postgres/src/backend/Analyser.js | 2 -- .../src/backend/sql/proceduresParameters.js | 6 +----- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 890de2368..4c3604b00 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -118,13 +118,15 @@ export interface ViewInfo extends SqlObjectInfo { columns: ColumnInfo[]; } +export type ParameterMode = 'IN' | 'OUT' | 'INOUT' | 'RETURN'; + export interface ParameterInfo { objectId?: string | number; schemaName: string; parameterName?: string; pureName: string; dataType: string; - isOutputParameter?: boolean; + parameterMode?: ParameterMode; } export interface ProcedureInfo extends SqlObjectInfo { parameters?: ParameterInfo[]; diff --git a/packages/web/src/appobj/ParameterAppObject.svelte b/packages/web/src/appobj/ParameterAppObject.svelte index adc875aea..4edae095d 100644 --- a/packages/web/src/appobj/ParameterAppObject.svelte +++ b/packages/web/src/appobj/ParameterAppObject.svelte @@ -12,7 +12,7 @@ {...$$restProps} {data} title={data.parameterName} - extInfo={data.isOutputParameter ? `${data.dataType} OUT` : data.dataType} + extInfo={data.parameterMode && data.parameterMode !== 'IN' ? `${data.dataType} ${data.parameterMode}` : data.dataType} icon={'icon parameter'} disableHover /> diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js index 1d1d98297..62f1f425d 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js @@ -13,7 +13,10 @@ SELECT p.max_length AS charMaxLength, p.precision AS precision, p.scale AS scale, - p.is_output AS isOutputParameter, + CASE + WHEN p.is_output = 1 THEN 'OUT' + ELSE 'IN' + END AS parameterMode, p.parameter_id AS parameterIndex, s.name as schemaName FROM diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index 14fe6c96a..7a007ef7e 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -8,7 +8,10 @@ SELECT p.max_length AS charMaxLength, p.precision AS precision, p.scale AS scale, - p.is_output AS isOutputParameter, + CASE + WHEN p.is_output = 1 THEN 'OUT' + ELSE 'IN' + END AS parameterMode, p.parameter_id AS parameterIndex s.name as schemaName FROM diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 87a899a59..bab737e0a 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -206,7 +206,6 @@ class Analyser extends DatabaseAnalyser { pureName: i.pure_name, parameterName: i.parameter_name, dataType: i.data_type, - isOutputParameter: i.is_output_parameter, parameterMode: i.parameter_mode, schemaName: i.schema_name, })); @@ -225,7 +224,6 @@ class Analyser extends DatabaseAnalyser { pureName: i.pure_name, parameterName: i.parameter_name, dataType: i.data_type, - isOutputParameter: i.is_output_parameter, parameterMode: i.parameter_mode, schemaName: i.schema_name, })); diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js index 1e37d3f2a..92612b8ad 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -7,11 +7,7 @@ SELECT args.parameter_mode, args.data_type AS data_type, args.ordinal_position AS parameter_index, - args.parameter_mode AS parameter_mode, - CASE - WHEN args.parameter_mode IN ('OUT', 'INOUT') THEN TRUE - ELSE FALSE - END AS is_output_parameter + args.parameter_mode AS parameter_mode FROM information_schema.routines proc LEFT JOIN From eca966bb904ded002fbe1fb09a3d98c92119bf99 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 13:38:36 +0100 Subject: [PATCH 10/38] fix: add null safety to getParametersSqlString --- plugins/dbgate-plugin-postgres/src/backend/Analyser.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index bab737e0a..ce023d849 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -52,7 +52,13 @@ function getColumnInfo( function getParametersSqlString(parameters = []) { if (!parameters?.length) return ''; - return parameters.map(i => `${i.parameterMode} ${i.parameterName} ${i.dataType.toUpperCase()}`).join(', '); + return parameters + .map(i => { + const mode = i.parameterMode ? `${i.parameterMode} ` : ''; + const dataType = i.dataType ? ` ${i.dataType.toUpperCase()}` : ''; + return mode + i.parameterName + dataType; + }) + .join(', '); } class Analyser extends DatabaseAnalyser { @@ -335,7 +341,7 @@ class Analyser extends DatabaseAnalyser { objectId: `functions:${func.schema_name}.${func.pure_name}`, createSql: `CREATE FUNCTION "${func.schema_name}"."${func.pure_name}"(${getParametersSqlString( functionNameToParameters[func.pure_name] - )}) RETURNS ${func.data_type} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`, + )}) RETURNS ${func.data_type.toUpperCase()} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`, pureName: func.pure_name, schemaName: func.schema_name, contentHash: func.hash_code, From d4326de087de212451f4e7db693ff3fe9d7f1365 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 13:53:35 +0100 Subject: [PATCH 11/38] fix: proceduresParameters mssql query --- .../dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index 7a007ef7e..1b9e9910f 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -12,7 +12,7 @@ SELECT WHEN p.is_output = 1 THEN 'OUT' ELSE 'IN' END AS parameterMode, - p.parameter_id AS parameterIndex + p.parameter_id AS parameterIndex, s.name as schemaName FROM sys.objects o From c516873541347bf2fb9ee8a4f9026596edd0184d Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 28 Nov 2024 21:05:06 +0100 Subject: [PATCH 12/38] feat: add parameters to mysql --- .../src/backend/Analyser.js | 44 +++++++++++++++++-- .../src/backend/sql/index.js | 2 + .../src/backend/sql/parameters.js | 22 ++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js diff --git a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js index ae68e0ce2..9419e507b 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js @@ -60,6 +60,18 @@ function getColumnInfo( }; } +function getParametersSqlString(parameters = []) { + if (!parameters?.length) return ''; + + return parameters + .map(i => { + const mode = i.parameterMode ? `${i.parameterMode} ` : ''; + const dataType = i.dataType ? ` ${i.dataType.toUpperCase()}` : ''; + return mode + i.parameterName + dataType; + }) + .join(', '); +} + class Analyser extends DatabaseAnalyser { constructor(dbhan, driver, version) { super(dbhan, driver, version); @@ -114,6 +126,24 @@ class Analyser extends DatabaseAnalyser { this.feedback({ analysingMessage: 'Loading programmables' }); const programmables = await this.analyserQuery('programmables', ['procedures', 'functions']); + const parameters = await this.analyserQuery('parameters', ['procedures', 'functions']); + + const functionParameters = parameters.rows.filter(x => x.routineType == 'FUNCTION'); + const functionNameToParameters = functionParameters.reduce((acc, row) => { + if (!acc[row.pureName]) acc[row.pureName] = []; + + acc[row.pureName].push(row); + return acc; + }, {}); + + const procedureParameters = parameters.rows.filter(x => x.routineType == 'PROCEDURE'); + const procedureNameToParameters = procedureParameters.reduce((acc, row) => { + if (!acc[row.pureName]) acc[row.pureName] = []; + + acc[row.pureName].push(row); + return acc; + }, {}); + this.feedback({ analysingMessage: 'Loading view texts' }); const viewTexts = await this.getViewTexts(views.rows.map(x => x.pureName)); this.feedback({ analysingMessage: 'Loading indexes' }); @@ -174,20 +204,26 @@ class Analyser extends DatabaseAnalyser { .map(x => _.omit(x, ['objectType'])) .map(x => ({ ...x, - createSql: `DELIMITER //\n\nCREATE PROCEDURE \`${x.pureName}\`()\n${x.routineDefinition}\n\nDELIMITER ;\n`, + createSql: `DELIMITER //\n\nCREATE PROCEDURE \`${x.pureName}\`(${getParametersSqlString( + procedureNameToParameters[x.pureName] + )})\n${x.routineDefinition}\n\nDELIMITER ;\n`, objectId: x.pureName, contentHash: _.isDate(x.modifyDate) ? x.modifyDate.toISOString() : x.modifyDate, + parameters: procedureNameToParameters[x.pureName], })), functions: programmables.rows .filter(x => x.objectType == 'FUNCTION') .map(x => _.omit(x, ['objectType'])) .map(x => ({ ...x, - createSql: `CREATE FUNCTION \`${x.pureName}\`()\nRETURNS ${x.returnDataType} ${ - x.isDeterministic == 'YES' ? 'DETERMINISTIC' : 'NOT DETERMINISTIC' - }\n${x.routineDefinition}`, + createSql: `CREATE FUNCTION \`${x.pureName}\`(${getParametersSqlString( + functionNameToParameters[x.pureName].filter(i => i.parameterMode !== 'RETURN') + )})\nRETURNS ${x.returnDataType} ${x.isDeterministic == 'YES' ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}\n${ + x.routineDefinition + }`, objectId: x.pureName, contentHash: _.isDate(x.modifyDate) ? x.modifyDate.toISOString() : x.modifyDate, + parameters: functionNameToParameters[x.pureName], })), }; this.feedback({ analysingMessage: null }); diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/index.js b/plugins/dbgate-plugin-mysql/src/backend/sql/index.js index 4839071e7..8c3e095fa 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/sql/index.js +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/index.js @@ -10,6 +10,7 @@ const procedureModifications = require('./procedureModifications'); const functionModifications = require('./functionModifications'); const uniqueNames = require('./uniqueNames'); const viewTexts = require('./viewTexts'); +const parameters = require('./parameters'); module.exports = { columns, @@ -19,6 +20,7 @@ module.exports = { tableModifications, views, programmables, + parameters, procedureModifications, functionModifications, indexes, diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js new file mode 100644 index 000000000..d884ea3d7 --- /dev/null +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js @@ -0,0 +1,22 @@ +module.exports = ` +SELECT + r.SPECIFIC_NAME AS pureName, + CASE + WHEN COALESCE(NULLIF(PARAMETER_MODE, ''), 'RETURN') = 'RETURN' THEN 'Return' + ELSE PARAMETER_NAME + END AS parameterName, + p.CHARACTER_MAXIMUM_LENGTH AS charMaxLength, + p.NUMERIC_PRECISION AS numericPrecision, + p.NUMERIC_SCALE AS numericScale, + p.DTD_IDENTIFIER AS dataType, + COALESCE(NULLIF(PARAMETER_MODE, ''), 'RETURN') AS parameterMode, + r.ROUTINE_TYPE AS routineType -- Function or Procedure +FROM + information_schema.PARAMETERS p +JOIN + information_schema.ROUTINES r +ON + p.SPECIFIC_NAME = r.SPECIFIC_NAME +WHERE + r.ROUTINE_SCHEMA = '#DATABASE#' AND r.ROUTINE_NAME =OBJECT_ID_CONDITION +`; From 446c615bb8df9c56e555c81f8ab786c8e285ee13 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 08:47:13 +0100 Subject: [PATCH 13/38] typo --- plugins/dbgate-plugin-postgres/src/backend/Analyser.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index ce023d849..4cadb1050 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -156,6 +156,7 @@ class Analyser extends DatabaseAnalyser { this.feedback({ analysingMessage: 'Loading routines' }); const routines = await this.analyserQuery('routines', ['procedures', 'functions']); + this.feedback({ analysingMessage: 'Loading routine parameters' }); const routineParametersRows = await this.analyserQuery('proceduresParameters'); this.feedback({ analysingMessage: 'Loading indexes' }); @@ -205,7 +206,7 @@ class Analyser extends DatabaseAnalyser { columnName: x.column_name, })); - const procedurePerameters = routineParametersRows.rows + const procedureParameters = routineParametersRows.rows .filter(i => i.routine_type == 'PROCEDURE') .map(i => ({ objectId: 'procedures:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, @@ -216,7 +217,7 @@ class Analyser extends DatabaseAnalyser { schemaName: i.schema_name, })); - const procedureNameToParameters = procedurePerameters.reduce((acc, row) => { + const procedureNameToParameters = procedureParameters.reduce((acc, row) => { if (!acc[row.pureName]) acc[row.pureName] = []; acc[row.pureName].push(row); From c26c9fae129500246967f1c502f2c9a56b9fd0f0 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 09:35:15 +0100 Subject: [PATCH 14/38] mssql parameters test --- .../__tests__/object-analyse.spec.js | 25 +++++++++ integration-tests/engines.js | 53 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/integration-tests/__tests__/object-analyse.spec.js b/integration-tests/__tests__/object-analyse.spec.js index e49e098df..4e15cef15 100644 --- a/integration-tests/__tests__/object-analyse.spec.js +++ b/integration-tests/__tests__/object-analyse.spec.js @@ -10,6 +10,14 @@ function flatSource() { ); } +function flatSourceParameters() { + return _.flatten( + engines.map(engine => + (engine.parameters || []).map(parameter => [engine.label, parameter.testName, parameter, engine]) + ) + ); +} + const obj1Match = expect.objectContaining({ pureName: 'obj1', }); @@ -86,4 +94,21 @@ describe('Object analyse', () => { expect(structure3[type][0]).toEqual(type.includes('views') ? view1Match : obj1Match); }) ); + + test.each(flatSourceParameters())( + 'Test parameters simple analyse - %s - %s', + testWrapper(async (conn, driver, testName, parameter, engine) => { + for (const sql of initSql) await driver.query(conn, sql, { discardResult: true }); + + await driver.query(conn, parameter.create, { discardResult: true }); + const structure = await driver.analyseFull(conn); + + const parameters = structure[parameter.objectTypeField][0].parameters; + + expect(parameters.length).toEqual(parameter.list.length); + for (let i = 0; i < parameters.length; i += 1) { + expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i])); + } + }) + ); }); diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 1bd0ab110..814594b9a 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -129,6 +129,59 @@ const engines = [ drop2: 'DROP PROCEDURE obj2', }, ], + parameters: [ + { + testName: 'simple', + create: 'CREATE PROCEDURE obj1 (@param1 int) AS SELECT id from t1', + objectTypeField: 'procedures', + list: [ + { + parameterName: '@param1', + parameterMode: 'IN', + dataType: 'int', + }, + ], + }, + { + testName: 'dataTypes', + create: 'CREATE PROCEDURE obj1 (@p1 bit, @p2 nvarchar(20), @p3 decimal(18,2), @p4 float) AS SELECT id from t1', + objectTypeField: 'procedures', + list: [ + { + parameterName: '@p1', + parameterMode: 'IN', + dataType: 'bit', + }, + { + parameterName: '@p2', + parameterMode: 'IN', + dataType: 'nvarchar(20)', + }, + { + parameterName: '@p3', + parameterMode: 'IN', + dataType: 'decimal(18,2)', + }, + { + parameterName: '@p4', + parameterMode: 'IN', + dataType: 'float', + }, + ], + }, + { + testName: 'outputParam', + create: 'CREATE PROCEDURE obj1 (@p1 int OUTPUT) AS SELECT id from t1', + objectTypeField: 'procedures', + list: [ + { + parameterName: '@p1', + parameterMode: 'OUT', + dataType: 'int', + }, + ], + }, + ], supportSchemas: true, supportRenameSqlObject: true, defaultSchemaName: 'dbo', From 0bef3f8e7183a79b2ac132fff1fe5bc3bec697ee Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 09:57:46 +0100 Subject: [PATCH 15/38] postgre procedure type tests --- integration-tests/engines.js | 59 ++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 814594b9a..c2b48a41b 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -105,6 +105,61 @@ const engines = [ res: '25', }, ], + + parameters: [ + { + testName: 'simple', + create: 'CREATE PROCEDURE obj1(a integer) LANGUAGE SQL AS $$ select * from t1 $$', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'integer', + }, + ], + }, + { + testName: 'dataTypes', + create: + 'CREATE PROCEDURE obj1(a integer, b varchar(20), c numeric(18,2)) LANGUAGE SQL AS $$ select * from t1 $$', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'integer', + }, + { + parameterName: 'b', + parameterMode: 'IN', + dataType: 'varchar(20)', + }, + { + parameterName: 'c', + parameterMode: 'IN', + dataType: 'numeric(18,2)', + }, + ], + }, + { + testName: 'paramModes', + create: 'CREATE PROCEDURE obj1(IN a integer, INOUT b integer) LANGUAGE SQL AS $$ select * from t1 $$', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'integer', + }, + { + parameterName: 'b', + parameterMode: 'INOUT', + dataType: 'integer', + }, + ], + }, + ], }, { label: 'SQL Server', @@ -243,8 +298,8 @@ const filterLocal = [ // filter local testing '-MySQL', '-MariaDB', - '-PostgreSQL', - 'SQL Server', + 'PostgreSQL', + '-SQL Server', '-SQLite', '-CockroachDB', '-ClickHouse', From ea76751e4a95ee4f7983b6e4d0ac3aadd0717e38 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 10:06:34 +0100 Subject: [PATCH 16/38] postgres function tests --- integration-tests/engines.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index c2b48a41b..74cac4adc 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -159,6 +159,34 @@ const engines = [ }, ], }, + { + testName: 'paramModesFunction', + objectTypeField: 'functions', + create: ` +create or replace function get_film_stat( + out min_len int, + out max_len int) +language plpgsql +as $$ +begin + select min(id), + max(id) + into min_len, max_len + from t1; +end;$$`, + list: [ + { + parameterName: 'min_len', + parameterMode: 'OUT', + dataType: 'integer', + }, + { + parameterName: 'max_len', + parameterMode: 'OUT', + dataType: 'integer', + }, + ], + }, ], }, { From 46c365c5cd1a0d337cee2d6479e6c6b808448988 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 10:29:12 +0100 Subject: [PATCH 17/38] mysql parameter types --- integration-tests/engines.js | 62 ++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 74cac4adc..991a1e17f 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -37,6 +37,64 @@ const engines = [ res: '25', }, ], + parameters: [ + { + testName: 'simple', + create: 'CREATE PROCEDURE obj1(a int) BEGIN SELECT * FROM t1; END', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'int', + }, + ], + }, + { + testName: 'paramTypes', + create: 'CREATE PROCEDURE obj1(a int, b varchar(50), c numeric(10,2)) BEGIN SELECT * FROM t1; END', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'int', + }, + { + parameterName: 'b', + parameterMode: 'IN', + dataType: 'varchar(50)', + }, + { + parameterName: 'c', + parameterMode: 'IN', + dataType: 'numeric(10,2)', + }, + ], + }, + { + testName: 'paramModes', + create: 'CREATE PROCEDURE obj1(IN a int, OUT b int, INOUT c int) BEGIN SELECT * FROM t1; END', + objectTypeField: 'procedures', + list: [ + { + parameterName: 'a', + parameterMode: 'IN', + dataType: 'int', + }, + { + parameterName: 'b', + parameterMode: 'OUT', + dataType: 'int', + }, + { + parameterName: 'c', + parameterMode: 'INOUT', + dataType: 'int', + }, + ], + } + ] }, { label: 'MariaDB', @@ -324,9 +382,9 @@ end;$$`, const filterLocal = [ // filter local testing - '-MySQL', + 'MySQL', '-MariaDB', - 'PostgreSQL', + '-PostgreSQL', '-SQL Server', '-SQLite', '-CockroachDB', From cf5ecb31506d5a43aeebdcb503f3b883e246a2d4 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 10:44:09 +0100 Subject: [PATCH 18/38] test create SQL --- .../__tests__/object-analyse.spec.js | 22 +++++++++++++++++++ integration-tests/engines.js | 18 +++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/integration-tests/__tests__/object-analyse.spec.js b/integration-tests/__tests__/object-analyse.spec.js index 4e15cef15..d973a42aa 100644 --- a/integration-tests/__tests__/object-analyse.spec.js +++ b/integration-tests/__tests__/object-analyse.spec.js @@ -111,4 +111,26 @@ describe('Object analyse', () => { } }) ); + + test.each(flatSourceParameters())( + 'Test parameters create SQL - %s - %s', + testWrapper(async (conn, driver, testName, parameter, engine) => { + for (const sql of initSql) await driver.query(conn, sql, { discardResult: true }); + + await driver.query(conn, parameter.create, { discardResult: true }); + const structure1 = await driver.analyseFull(conn); + await driver.query(conn, parameter.drop, { discardResult: true }); + + const obj = structure1[parameter.objectTypeField][0]; + await driver.query(conn, obj.createSql, { discardResult: true }); + + const structure2 = await driver.analyseFull(conn); + const parameters = structure2[parameter.objectTypeField][0].parameters; + + expect(parameters.length).toEqual(parameter.list.length); + for (let i = 0; i < parameters.length; i += 1) { + expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i])); + } + }) + ); }); diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 991a1e17f..70ae9fc41 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -41,6 +41,7 @@ const engines = [ { testName: 'simple', create: 'CREATE PROCEDURE obj1(a int) BEGIN SELECT * FROM t1; END', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -53,6 +54,7 @@ const engines = [ { testName: 'paramTypes', create: 'CREATE PROCEDURE obj1(a int, b varchar(50), c numeric(10,2)) BEGIN SELECT * FROM t1; END', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -75,6 +77,7 @@ const engines = [ { testName: 'paramModes', create: 'CREATE PROCEDURE obj1(IN a int, OUT b int, INOUT c int) BEGIN SELECT * FROM t1; END', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -93,8 +96,8 @@ const engines = [ dataType: 'int', }, ], - } - ] + }, + ], }, { label: 'MariaDB', @@ -168,6 +171,7 @@ const engines = [ { testName: 'simple', create: 'CREATE PROCEDURE obj1(a integer) LANGUAGE SQL AS $$ select * from t1 $$', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -181,6 +185,7 @@ const engines = [ testName: 'dataTypes', create: 'CREATE PROCEDURE obj1(a integer, b varchar(20), c numeric(18,2)) LANGUAGE SQL AS $$ select * from t1 $$', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -203,6 +208,7 @@ const engines = [ { testName: 'paramModes', create: 'CREATE PROCEDURE obj1(IN a integer, INOUT b integer) LANGUAGE SQL AS $$ select * from t1 $$', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -232,6 +238,7 @@ begin into min_len, max_len from t1; end;$$`, + drop: 'DROP FUNCTION obj1', list: [ { parameterName: 'min_len', @@ -274,6 +281,7 @@ end;$$`, { testName: 'simple', create: 'CREATE PROCEDURE obj1 (@param1 int) AS SELECT id from t1', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -286,6 +294,7 @@ end;$$`, { testName: 'dataTypes', create: 'CREATE PROCEDURE obj1 (@p1 bit, @p2 nvarchar(20), @p3 decimal(18,2), @p4 float) AS SELECT id from t1', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -313,6 +322,7 @@ end;$$`, { testName: 'outputParam', create: 'CREATE PROCEDURE obj1 (@p1 int OUTPUT) AS SELECT id from t1', + drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { @@ -382,10 +392,10 @@ end;$$`, const filterLocal = [ // filter local testing - 'MySQL', + '-MySQL', '-MariaDB', '-PostgreSQL', - '-SQL Server', + 'SQL Server', '-SQLite', '-CockroachDB', '-ClickHouse', From a66dc03b99fa505781deefe760a338cfbed2e8b6 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 29 Nov 2024 10:48:15 +0100 Subject: [PATCH 19/38] params test - added object for test parent object match --- integration-tests/__tests__/object-analyse.spec.js | 8 +++++--- integration-tests/engines.js | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/integration-tests/__tests__/object-analyse.spec.js b/integration-tests/__tests__/object-analyse.spec.js index d973a42aa..cfd0a0326 100644 --- a/integration-tests/__tests__/object-analyse.spec.js +++ b/integration-tests/__tests__/object-analyse.spec.js @@ -99,11 +99,12 @@ describe('Object analyse', () => { 'Test parameters simple analyse - %s - %s', testWrapper(async (conn, driver, testName, parameter, engine) => { for (const sql of initSql) await driver.query(conn, sql, { discardResult: true }); + for (const sql of engine.parametersOtherSql) await driver.query(conn, sql, { discardResult: true }); await driver.query(conn, parameter.create, { discardResult: true }); const structure = await driver.analyseFull(conn); - const parameters = structure[parameter.objectTypeField][0].parameters; + const parameters = structure[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters; expect(parameters.length).toEqual(parameter.list.length); for (let i = 0; i < parameters.length; i += 1) { @@ -116,16 +117,17 @@ describe('Object analyse', () => { 'Test parameters create SQL - %s - %s', testWrapper(async (conn, driver, testName, parameter, engine) => { for (const sql of initSql) await driver.query(conn, sql, { discardResult: true }); + for (const sql of engine.parametersOtherSql) await driver.query(conn, sql, { discardResult: true }); await driver.query(conn, parameter.create, { discardResult: true }); const structure1 = await driver.analyseFull(conn); await driver.query(conn, parameter.drop, { discardResult: true }); - const obj = structure1[parameter.objectTypeField][0]; + const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1'); await driver.query(conn, obj.createSql, { discardResult: true }); const structure2 = await driver.analyseFull(conn); - const parameters = structure2[parameter.objectTypeField][0].parameters; + const parameters = structure2[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters; expect(parameters.length).toEqual(parameter.list.length); for (let i = 0; i < parameters.length; i += 1) { diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 70ae9fc41..6f28f0dc2 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -37,6 +37,7 @@ const engines = [ res: '25', }, ], + parametersOtherSql: ['CREATE PROCEDURE obj2(a int, b int) BEGIN SELECT * FROM t1; END'], parameters: [ { testName: 'simple', @@ -167,6 +168,7 @@ const engines = [ }, ], + parametersOtherSql: ['CREATE PROCEDURE obj2(a integer, b integer) LANGUAGE SQL AS $$ select * from t1 $$'], parameters: [ { testName: 'simple', @@ -277,6 +279,7 @@ end;$$`, drop2: 'DROP PROCEDURE obj2', }, ], + parametersOtherSql: ['CREATE PROCEDURE obj2 (@p1 int, @p2 int) AS SELECT id from t1'], parameters: [ { testName: 'simple', From 666122f265b95f30d772c9a5d65345ae51b116d9 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Tue, 3 Dec 2024 09:46:12 +0100 Subject: [PATCH 20/38] add mysql create/drop procedure test --- .../__tests__/object-analyse.spec.js | 4 ++-- integration-tests/engines.js | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/integration-tests/__tests__/object-analyse.spec.js b/integration-tests/__tests__/object-analyse.spec.js index cfd0a0326..db36fc92b 100644 --- a/integration-tests/__tests__/object-analyse.spec.js +++ b/integration-tests/__tests__/object-analyse.spec.js @@ -86,7 +86,7 @@ describe('Object analyse', () => { const structure2 = await driver.analyseIncremental(conn, structure1); expect(structure2[type].length).toEqual(0); - await driver.query(conn, structure1[type][0].createSql, { discardResult: true }); + await driver.script(conn, structure1[type][0].createSql, { discardResult: true }); const structure3 = await driver.analyseIncremental(conn, structure2); @@ -124,7 +124,7 @@ describe('Object analyse', () => { await driver.query(conn, parameter.drop, { discardResult: true }); const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1'); - await driver.query(conn, obj.createSql, { discardResult: true }); + await driver.script(conn, obj.createSql, { discardResult: true }); const structure2 = await driver.analyseFull(conn); const parameters = structure2[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters; diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 6f28f0dc2..215320a87 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -28,7 +28,16 @@ const engines = [ port: 15001, }, // skipOnCI: true, - objects: [views], + objects: [ + views, + { + type: 'procedures', + create1: 'CREATE PROCEDURE obj1() BEGIN SELECT * FROM t1; END', + create2: 'CREATE PROCEDURE obj2() BEGIN SELECT * FROM t2; END', + drop1: 'DROP PROCEDURE obj1', + drop2: 'DROP PROCEDURE obj2', + }, + ], dbSnapshotBySeconds: true, dumpFile: 'data/chinook-mysql.sql', dumpChecks: [ @@ -395,10 +404,10 @@ end;$$`, const filterLocal = [ // filter local testing - '-MySQL', + 'MySQL', '-MariaDB', '-PostgreSQL', - 'SQL Server', + '-SQL Server', '-SQLite', '-CockroachDB', '-ClickHouse', From 352e426e171222366450974080959d34781a6ac9 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Tue, 3 Dec 2024 09:48:56 +0100 Subject: [PATCH 21/38] fix --- integration-tests/__tests__/object-analyse.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/__tests__/object-analyse.spec.js b/integration-tests/__tests__/object-analyse.spec.js index db36fc92b..f94223b69 100644 --- a/integration-tests/__tests__/object-analyse.spec.js +++ b/integration-tests/__tests__/object-analyse.spec.js @@ -86,7 +86,7 @@ describe('Object analyse', () => { const structure2 = await driver.analyseIncremental(conn, structure1); expect(structure2[type].length).toEqual(0); - await driver.script(conn, structure1[type][0].createSql, { discardResult: true }); + await driver.script(conn, structure1[type][0].createSql); const structure3 = await driver.analyseIncremental(conn, structure2); @@ -124,7 +124,7 @@ describe('Object analyse', () => { await driver.query(conn, parameter.drop, { discardResult: true }); const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1'); - await driver.script(conn, obj.createSql, { discardResult: true }); + await driver.script(conn, obj.createSql); const structure2 = await driver.analyseFull(conn); const parameters = structure2[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters; From 0eca5dd95d98b6cea9744e1568a85a3d46e2f0c4 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 10:37:36 +0100 Subject: [PATCH 22/38] fix: typos --- plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js index 72b4060f9..37b227d08 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js +++ b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js @@ -129,7 +129,7 @@ class MsSqlAnalyser extends DatabaseAnalyser { this.feedback({ analysingMessage: 'Loading procedures & functions' }); const programmableRows = await this.analyserQuery('programmables', ['procedures', 'functions']); - const prodceureParameterRows = await this.analyserQuery('proceduresParameters'); + const procedureParameterRows = await this.analyserQuery('proceduresParameters'); const functionParameterRows = await this.analyserQuery('functionParameters'); this.feedback({ analysingMessage: 'Loading view columns' }); @@ -172,12 +172,12 @@ class MsSqlAnalyser extends DatabaseAnalyser { columns: viewColumnRows.rows.filter(col => col.objectId == row.objectId).map(getColumnInfo), })); - const prodceureParameter = prodceureParameterRows.rows.map(row => ({ + const procedureParameter = procedureParameterRows.rows.map(row => ({ ...row, fullDataType: getFullDataTypeName(row), })); - const prodceureToParameters = prodceureParameter.reduce((acc, parameter) => { + const prodceureToParameters = procedureParameter.reduce((acc, parameter) => { if (!acc[parameter.parentObjectId]) acc[parameter.parentObjectId] = []; acc[parameter.parentObjectId].push(parameter); From 5c7d2bfd85aef19b521bc6dad44df997a339760f Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 11:01:47 +0100 Subject: [PATCH 23/38] fix: update parameter group keys --- packages/types/dbinfo.d.ts | 1 - .../src/backend/Analyser.js | 16 ++++++++-------- .../src/backend/Analyser.js | 18 ++++++++---------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 4c3604b00..24d379c61 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -121,7 +121,6 @@ export interface ViewInfo extends SqlObjectInfo { export type ParameterMode = 'IN' | 'OUT' | 'INOUT' | 'RETURN'; export interface ParameterInfo { - objectId?: string | number; schemaName: string; parameterName?: string; pureName: string; diff --git a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js index 9419e507b..839967c72 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js @@ -130,17 +130,17 @@ class Analyser extends DatabaseAnalyser { const functionParameters = parameters.rows.filter(x => x.routineType == 'FUNCTION'); const functionNameToParameters = functionParameters.reduce((acc, row) => { - if (!acc[row.pureName]) acc[row.pureName] = []; + if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; - acc[row.pureName].push(row); + acc[`${row.schemaName}.${row.pureName}`].push(row); return acc; }, {}); const procedureParameters = parameters.rows.filter(x => x.routineType == 'PROCEDURE'); const procedureNameToParameters = procedureParameters.reduce((acc, row) => { - if (!acc[row.pureName]) acc[row.pureName] = []; + if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; - acc[row.pureName].push(row); + acc[`${row.schemaName}.${row.pureName}`].push(row); return acc; }, {}); @@ -205,11 +205,11 @@ class Analyser extends DatabaseAnalyser { .map(x => ({ ...x, createSql: `DELIMITER //\n\nCREATE PROCEDURE \`${x.pureName}\`(${getParametersSqlString( - procedureNameToParameters[x.pureName] + procedureNameToParameters[`${x.schemaName}.${x.pureName}`] )})\n${x.routineDefinition}\n\nDELIMITER ;\n`, objectId: x.pureName, contentHash: _.isDate(x.modifyDate) ? x.modifyDate.toISOString() : x.modifyDate, - parameters: procedureNameToParameters[x.pureName], + parameters: procedureNameToParameters[`${x.schemaName}.${x.pureName}`], })), functions: programmables.rows .filter(x => x.objectType == 'FUNCTION') @@ -217,13 +217,13 @@ class Analyser extends DatabaseAnalyser { .map(x => ({ ...x, createSql: `CREATE FUNCTION \`${x.pureName}\`(${getParametersSqlString( - functionNameToParameters[x.pureName].filter(i => i.parameterMode !== 'RETURN') + functionNameToParameters[`${x.schemaName}.${x.pureName}`].filter(i => i.parameterMode !== 'RETURN') )})\nRETURNS ${x.returnDataType} ${x.isDeterministic == 'YES' ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}\n${ x.routineDefinition }`, objectId: x.pureName, contentHash: _.isDate(x.modifyDate) ? x.modifyDate.toISOString() : x.modifyDate, - parameters: functionNameToParameters[x.pureName], + parameters: functionNameToParameters[`${x.schemaName}.${x.pureName}`], })), }; this.feedback({ analysingMessage: null }); diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 4cadb1050..60dbfd76a 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -209,7 +209,6 @@ class Analyser extends DatabaseAnalyser { const procedureParameters = routineParametersRows.rows .filter(i => i.routine_type == 'PROCEDURE') .map(i => ({ - objectId: 'procedures:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, pureName: i.pure_name, parameterName: i.parameter_name, dataType: i.data_type, @@ -218,8 +217,8 @@ class Analyser extends DatabaseAnalyser { })); const procedureNameToParameters = procedureParameters.reduce((acc, row) => { - if (!acc[row.pureName]) acc[row.pureName] = []; - acc[row.pureName].push(row); + if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; + acc[`${row.schemaName}.${row.pureName}`].push(row); return acc; }, {}); @@ -227,7 +226,6 @@ class Analyser extends DatabaseAnalyser { const functionParameters = routineParametersRows.rows .filter(i => i.routine_type == 'FUNCTION') .map(i => ({ - objectId: 'functions:' + i.specific_schema + '.' + i.routine_name + '@' + i.pure_name, pureName: i.pure_name, parameterName: i.parameter_name, dataType: i.data_type, @@ -236,8 +234,8 @@ class Analyser extends DatabaseAnalyser { })); const functionNameToParameters = functionParameters.reduce((acc, row) => { - if (!acc[row.pureName]) acc[row.pureName] = []; - acc[row.pureName].push(row); + if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; + acc[`${row.schemaName}.${row.pureName}`].push(row); return acc; }, {}); @@ -331,22 +329,22 @@ class Analyser extends DatabaseAnalyser { pureName: proc.pure_name, schemaName: proc.schema_name, createSql: `CREATE PROCEDURE "${proc.schema_name}"."${proc.pure_name}"(${getParametersSqlString( - procedureNameToParameters[proc.pure_name] + procedureNameToParameters[`${proc.schema_name}.${proc.pure_name}`] )}) LANGUAGE ${proc.language}\nAS\n$$\n${proc.definition}\n$$`, contentHash: proc.hash_code, - parameters: procedureNameToParameters[proc.pure_name], + parameters: procedureNameToParameters[`${proc.schema_name}.${proc.pure_name}`], })), functions: routines.rows .filter(x => x.object_type == 'FUNCTION') .map(func => ({ objectId: `functions:${func.schema_name}.${func.pure_name}`, createSql: `CREATE FUNCTION "${func.schema_name}"."${func.pure_name}"(${getParametersSqlString( - functionNameToParameters[func.pure_name] + functionNameToParameters[`${func.schema_name}.${func.pure_name}`] )}) RETURNS ${func.data_type.toUpperCase()} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`, pureName: func.pure_name, schemaName: func.schema_name, contentHash: func.hash_code, - parameters: functionNameToParameters[func.pure_name], + parameters: functionNameToParameters[`${func.schema_name}.${func.pure_name}`], })), }; From d3018a31365ae669a13f71d1f20bbacec12d59da Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 11:31:09 +0100 Subject: [PATCH 24/38] fix: correct function name in tests --- integration-tests/engines.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index 215320a87..ed34a91e4 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -238,7 +238,7 @@ const engines = [ testName: 'paramModesFunction', objectTypeField: 'functions', create: ` -create or replace function get_film_stat( +create or replace function obj1( out min_len int, out max_len int) language plpgsql From 10fc62ceb7fbaccfee499a79571b51d6189e911b Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 11:37:35 +0100 Subject: [PATCH 25/38] fix: do not order pssql params by name --- .../src/backend/sql/proceduresParameters.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js index 92612b8ad..753127d14 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -26,6 +26,5 @@ WHERE ) ORDER BY schema_name, - parameter_name, args.ordinal_position; `; From 32ddb9c4c7faa83fc6437b9e19dbd32df54e7bb8 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 12:46:01 +0100 Subject: [PATCH 26/38] fix: normalize pssql parameters datatype --- integration-tests/engines.js | 4 ++-- plugins/dbgate-plugin-postgres/src/backend/Analyser.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index ed34a91e4..fc44c5548 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -207,12 +207,12 @@ const engines = [ { parameterName: 'b', parameterMode: 'IN', - dataType: 'varchar(20)', + dataType: 'varchar', }, { parameterName: 'c', parameterMode: 'IN', - dataType: 'numeric(18,2)', + dataType: 'numeric', }, ], }, diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 60dbfd76a..fbf6b1c4d 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -211,7 +211,7 @@ class Analyser extends DatabaseAnalyser { .map(i => ({ pureName: i.pure_name, parameterName: i.parameter_name, - dataType: i.data_type, + dataType: normalizeTypeName(i.data_type), parameterMode: i.parameter_mode, schemaName: i.schema_name, })); @@ -228,7 +228,7 @@ class Analyser extends DatabaseAnalyser { .map(i => ({ pureName: i.pure_name, parameterName: i.parameter_name, - dataType: i.data_type, + dataType: normalizeTypeName(i.data_type), parameterMode: i.parameter_mode, schemaName: i.schema_name, })); From 21702f1593624a11e48aea63b46d3d2a3bd3e443 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 13:03:05 +0100 Subject: [PATCH 27/38] fix: do not fetch pssql params w/o name --- .../src/backend/sql/proceduresParameters.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js index 753127d14..667cfed09 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-postgres/src/backend/sql/proceduresParameters.js @@ -16,6 +16,7 @@ LEFT JOIN AND proc.specific_name = args.specific_name WHERE proc.specific_schema NOT IN ('pg_catalog', 'information_schema') -- Exclude system schemas + AND args.parameter_name IS NOT NULL AND proc.routine_type IN ('PROCEDURE', 'FUNCTION') -- Filter for procedures AND proc.specific_schema !~ '^_timescaledb_' AND proc.specific_schema =SCHEMA_NAME_CONDITION From 81cea4c0f2da866b72bcf9b599acd172836c08da Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 13:07:50 +0100 Subject: [PATCH 28/38] fix: pssql params to string helper --- plugins/dbgate-plugin-postgres/src/backend/Analyser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index fbf6b1c4d..90bb94ab8 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -56,7 +56,8 @@ function getParametersSqlString(parameters = []) { .map(i => { const mode = i.parameterMode ? `${i.parameterMode} ` : ''; const dataType = i.dataType ? ` ${i.dataType.toUpperCase()}` : ''; - return mode + i.parameterName + dataType; + const parameterName = i.parameterName ?? ''; + return `${mode}${parameterName}${dataType}`; }) .join(', '); } From 222ea07cf233feff12cb9de182a4015ac4a7209a Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 14:11:04 +0100 Subject: [PATCH 29/38] fix: update mssql params queries --- .../src/backend/sql/functionParameters.js | 19 ++++++++++++++++--- .../src/backend/sql/proceduresParameters.js | 13 ++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js index 62f1f425d..2a255d939 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/functionParameters.js @@ -10,9 +10,22 @@ SELECT p.name END AS parameterName, TYPE_NAME(p.user_type_id) AS dataType, - p.max_length AS charMaxLength, - p.precision AS precision, - p.scale AS scale, + CASE + WHEN TYPE_NAME(p.user_type_id) = 'nvarchar' THEN p.max_length / 2 + ELSE p.max_length + END AS charMaxLength, + CASE + WHEN p.is_output = 1 THEN 'OUT' + ELSE 'IN' + END AS parameterMode, + CASE + WHEN TYPE_NAME(p.user_type_id) IN ('numeric', 'decimal') THEN p.precision + ELSE NULL + END AS numericPrecision, + CASE + WHEN TYPE_NAME(p.user_type_id) IN ('numeric', 'decimal') THEN p.scale + ELSE NULL + END AS numericScale, CASE WHEN p.is_output = 1 THEN 'OUT' ELSE 'IN' diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index 1b9e9910f..ba11582bd 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -5,13 +5,24 @@ SELECT o.name as pureName, p.name AS parameterName, TYPE_NAME(p.user_type_id) AS dataType, - p.max_length AS charMaxLength, + CASE + WHEN TYPE_NAME(p.user_type_id) = 'nvarchar' THEN p.max_length / 2 + ELSE p.max_length + END AS charMaxLength, p.precision AS precision, p.scale AS scale, CASE WHEN p.is_output = 1 THEN 'OUT' ELSE 'IN' END AS parameterMode, + CASE + WHEN TYPE_NAME(p.user_type_id) IN ('numeric', 'decimal') THEN p.precision + ELSE NULL + END AS numericPrecision, + CASE + WHEN TYPE_NAME(p.user_type_id) IN ('numeric', 'decimal') THEN p.scale + ELSE NULL + END AS numericScale, p.parameter_id AS parameterIndex, s.name as schemaName FROM From e40357c052576b6e783c17d4303371ca031c05ad Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 14:11:26 +0100 Subject: [PATCH 30/38] fix: replace fullDataType with dataType in mssql params --- plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js index 37b227d08..79b040f76 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js +++ b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js @@ -174,7 +174,7 @@ class MsSqlAnalyser extends DatabaseAnalyser { const procedureParameter = procedureParameterRows.rows.map(row => ({ ...row, - fullDataType: getFullDataTypeName(row), + dataType: getFullDataTypeName(row), })); const prodceureToParameters = procedureParameter.reduce((acc, parameter) => { @@ -195,7 +195,7 @@ class MsSqlAnalyser extends DatabaseAnalyser { const functionParameters = functionParameterRows.rows.map(row => ({ ...row, - fullDataType: getFullDataTypeName(row), + dataType: getFullDataTypeName(row), })); const functionToParameters = functionParameters.reduce((acc, parameter) => { From 1a4009a6b25280515c1ec77f623aff8b5edfc274 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 14:13:31 +0100 Subject: [PATCH 31/38] chore: remove unused query results --- .../dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js index ba11582bd..d02b5fcb1 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/proceduresParameters.js @@ -9,8 +9,6 @@ SELECT WHEN TYPE_NAME(p.user_type_id) = 'nvarchar' THEN p.max_length / 2 ELSE p.max_length END AS charMaxLength, - p.precision AS precision, - p.scale AS scale, CASE WHEN p.is_output = 1 THEN 'OUT' ELSE 'IN' From 029866071466ac54e82e69b10414aa4a922071b0 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 15:32:21 +0100 Subject: [PATCH 32/38] fix: add shchema to mysql programables query --- plugins/dbgate-plugin-mysql/src/backend/sql/programmables.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/programmables.js b/plugins/dbgate-plugin-mysql/src/backend/sql/programmables.js index f6442fcc1..588c04012 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/sql/programmables.js +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/programmables.js @@ -1,5 +1,6 @@ module.exports = ` select + ROUTINE_SCHEMA AS schemaName, ROUTINE_NAME as pureName, ROUTINE_TYPE as objectType, COALESCE(LAST_ALTERED, CREATED) as modifyDate, From bb185d9e9fd891a1aace6e61be57ad53f7e82479 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 15:32:33 +0100 Subject: [PATCH 33/38] fix: add join on schema for mysql params query --- plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js index d884ea3d7..30d455a5d 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js @@ -1,5 +1,6 @@ module.exports = ` -SELECT +SELECT DISTINCT + r.ROUTINE_SCHEMA AS schemaName, r.SPECIFIC_NAME AS pureName, CASE WHEN COALESCE(NULLIF(PARAMETER_MODE, ''), 'RETURN') = 'RETURN' THEN 'Return' @@ -16,7 +17,7 @@ FROM JOIN information_schema.ROUTINES r ON - p.SPECIFIC_NAME = r.SPECIFIC_NAME + p.SPECIFIC_NAME = r.SPECIFIC_NAME AND r.ROUTINE_SCHEMA = p.SPECIFIC_SCHEMA WHERE r.ROUTINE_SCHEMA = '#DATABASE#' AND r.ROUTINE_NAME =OBJECT_ID_CONDITION `; From a72a03cc3a1c3086501373520d8572357a99fc04 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 15:33:11 +0100 Subject: [PATCH 34/38] fix: add null safety for mysql function w/o params --- plugins/dbgate-plugin-mysql/src/backend/Analyser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js index 839967c72..7f379d92f 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js @@ -217,7 +217,7 @@ class Analyser extends DatabaseAnalyser { .map(x => ({ ...x, createSql: `CREATE FUNCTION \`${x.pureName}\`(${getParametersSqlString( - functionNameToParameters[`${x.schemaName}.${x.pureName}`].filter(i => i.parameterMode !== 'RETURN') + functionNameToParameters[`${x.schemaName}.${x.pureName}`]?.filter(i => i.parameterMode !== 'RETURN') )})\nRETURNS ${x.returnDataType} ${x.isDeterministic == 'YES' ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}\n${ x.routineDefinition }`, From 57a997adc333a4c925de788d18672101d60374f9 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 15:39:05 +0100 Subject: [PATCH 35/38] fix: expect decimal for numeric params in mysql tests --- integration-tests/engines.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/engines.js b/integration-tests/engines.js index fc44c5548..6ea74f7ab 100644 --- a/integration-tests/engines.js +++ b/integration-tests/engines.js @@ -80,7 +80,7 @@ const engines = [ { parameterName: 'c', parameterMode: 'IN', - dataType: 'numeric(10,2)', + dataType: 'decimal(10,2)', }, ], }, From 27188eb2c57ba3b747e8f9ee9b1f854cd69b9771 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 15:39:22 +0100 Subject: [PATCH 36/38] fix: normalize type name for mysql params --- .../dbgate-plugin-mysql/src/backend/Analyser.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js index 7f379d92f..0e4565568 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js @@ -15,6 +15,11 @@ function quoteDefaultValue(value) { return value; } +function normalizeTypeName(typeName) { + if (/int\(\d+\)/.test(typeName)) return 'int'; + return typeName; +} + function getColumnInfo( { isNullable, @@ -132,7 +137,10 @@ class Analyser extends DatabaseAnalyser { const functionNameToParameters = functionParameters.reduce((acc, row) => { if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; - acc[`${row.schemaName}.${row.pureName}`].push(row); + acc[`${row.schemaName}.${row.pureName}`].push({ + ...row, + dataType: normalizeTypeName(row.dataType), + }); return acc; }, {}); @@ -140,7 +148,10 @@ class Analyser extends DatabaseAnalyser { const procedureNameToParameters = procedureParameters.reduce((acc, row) => { if (!acc[`${row.schemaName}.${row.pureName}`]) acc[`${row.schemaName}.${row.pureName}`] = []; - acc[`${row.schemaName}.${row.pureName}`].push(row); + acc[`${row.schemaName}.${row.pureName}`].push({ + ...row, + dataType: normalizeTypeName(row.dataType), + }); return acc; }, {}); From b6399c827181566795f0cfc50c777a064be335a6 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Tue, 3 Dec 2024 16:05:23 +0100 Subject: [PATCH 37/38] try to fix test --- plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js index 30d455a5d..46c2f4d1b 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js @@ -11,7 +11,8 @@ SELECT DISTINCT p.NUMERIC_SCALE AS numericScale, p.DTD_IDENTIFIER AS dataType, COALESCE(NULLIF(PARAMETER_MODE, ''), 'RETURN') AS parameterMode, - r.ROUTINE_TYPE AS routineType -- Function or Procedure + r.ROUTINE_TYPE AS routineType, -- Function or Procedure + p.ORDINAL_POSITION AS ordinalPosition FROM information_schema.PARAMETERS p JOIN @@ -20,4 +21,6 @@ ON p.SPECIFIC_NAME = r.SPECIFIC_NAME AND r.ROUTINE_SCHEMA = p.SPECIFIC_SCHEMA WHERE r.ROUTINE_SCHEMA = '#DATABASE#' AND r.ROUTINE_NAME =OBJECT_ID_CONDITION +ORDER BY + r.ROUTINE_SCHEMA, r.SPECIFIC_NAME, p.ORDINAL_POSITION `; From 4e4eb39a1927750b31a1729b13d111c12afa3760 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Tue, 3 Dec 2024 16:19:57 +0100 Subject: [PATCH 38/38] fix: remove distinct from mysql params query --- plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js index 46c2f4d1b..e3091da1d 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js +++ b/plugins/dbgate-plugin-mysql/src/backend/sql/parameters.js @@ -1,5 +1,5 @@ module.exports = ` -SELECT DISTINCT +SELECT r.ROUTINE_SCHEMA AS schemaName, r.SPECIFIC_NAME AS pureName, CASE