diff --git a/plugins/dbgate-plugin-mssql/src/backend/driver.js b/plugins/dbgate-plugin-mssql/src/backend/driver.js index 8d16e35b8..7360b998c 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/driver.js +++ b/plugins/dbgate-plugin-mssql/src/backend/driver.js @@ -9,6 +9,7 @@ const lock = new AsyncLock(); const { tediousConnect, tediousQueryCore, tediousReadQuery, tediousStream } = require('./tediousDriver'); const { nativeConnect, nativeQueryCore, nativeReadQuery, nativeStream } = require('./nativeDriver'); const { getLogger } = global.DBGATE_PACKAGES['dbgate-tools']; +const sql = require('./sql'); const logger = getLogger('mssqlDriver'); @@ -148,9 +149,49 @@ const driver = { return res; }, async listDatabases(dbhan) { - const { rows } = await this.query(dbhan, 'SELECT name FROM sys.databases order by name'); + const { rows } = await this.query(dbhan, sql.listDatabases); return rows; }, + + async listProcesses(dbhan) { + const { rows } = await this.query(dbhan, sql.listProcesses); + return rows; + }, + + async listVariables(dbhan) { + const { rows } = await this.query(dbhan, sql.listVariables); + return rows; + }, + + async killProcess(dbhan, processId) { + await this.query(dbhan, `KILL ${processId}`); + }, + + async serverSummary(dbhan) { + const [variables, processes, databases] = await Promise.all([ + this.listVariables(dbhan), + this.listProcesses(dbhan), + this.listDatabases(dbhan), + ]); + + return { + variables: variables, + processes: processes, + databases: { + rows: databases, + columns: [ + { header: 'Database', fieldName: 'name', type: 'data' }, + { header: 'Status', fieldName: 'status', type: 'data' }, + { header: 'Recovery Model', fieldName: 'recoveryModel', type: 'data' }, + { header: 'Compatibility Level', fieldName: 'compatibilityLevel', type: 'data' }, + { header: 'Read Only', fieldName: 'isReadOnly', type: 'data' }, + { header: 'Data Size', fieldName: 'sizeOnDisk', type: 'fileSize' }, + { header: 'Log Size', fieldName: 'logSizeOnDisk', type: 'fileSize' }, + ], + }, + }; + }, + getRedirectAuthUrl(connection, options) { if (connection.authType != 'msentra') return null; return authProxy.authProxyGetRedirectUrl({ diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/index.js b/plugins/dbgate-plugin-mssql/src/backend/sql/index.js index 4125b1ebd..f9426419f 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/sql/index.js +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/index.js @@ -13,6 +13,9 @@ const viewColumns = require('./viewColumns'); const indexes = require('./indexes'); const indexcols = require('./indexcols'); const triggers = require('./triggers'); +const listVariables = require('./listVariables'); +const listDatabases = require('./listDatabases'); +const listProcesses = require('./listProcesses'); module.exports = { columns, @@ -30,4 +33,7 @@ module.exports = { indexcols, tableSizes, triggers, + listVariables, + listDatabases, + listProcesses, }; diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/listDatabases.js b/plugins/dbgate-plugin-mssql/src/backend/sql/listDatabases.js new file mode 100644 index 000000000..751c54b39 --- /dev/null +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/listDatabases.js @@ -0,0 +1,17 @@ +module.exports = ` + SELECT + d.name, + d.database_id, + d.state_desc as status, + d.recovery_model_desc as recoveryModel, + d.collation_name as collation, + d.compatibility_level as compatibilityLevel, + d.is_read_only as isReadOnly, + CAST(SUM(CASE WHEN mf.type = 0 THEN mf.size * 8192.0 ELSE 0 END) AS BIGINT) AS sizeOnDisk, + CAST(SUM(CASE WHEN mf.type = 1 THEN mf.size * 8192.0 ELSE 0 END) AS BIGINT) AS logSizeOnDisk + FROM sys.databases d + LEFT JOIN sys.master_files mf ON d.database_id = mf.database_id + GROUP BY d.name, d.database_id, d.state_desc, d.recovery_model_desc, d.collation_name, + d.compatibility_level, d.is_read_only + ORDER BY d.name +`; diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/listProcesses.js b/plugins/dbgate-plugin-mssql/src/backend/sql/listProcesses.js new file mode 100644 index 000000000..30ffe5768 --- /dev/null +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/listProcesses.js @@ -0,0 +1,11 @@ +module.exports = ` +SELECT + session_id as processId, + ISNULL(host_name, 'Unknown') + ':' + ISNULL(CAST(host_process_id AS VARCHAR(10)), '?') as client, + ISNULL(DB_NAME(database_id), 'master') as namespace, + ISNULL(DATEDIFF(SECOND, last_request_start_time, GETDATE()), 0) as runningTime, + status as state +FROM sys.dm_exec_sessions +WHERE is_user_process = 1 +ORDER BY session_id +`; diff --git a/plugins/dbgate-plugin-mssql/src/backend/sql/listVariables.js b/plugins/dbgate-plugin-mssql/src/backend/sql/listVariables.js new file mode 100644 index 000000000..a6543c759 --- /dev/null +++ b/plugins/dbgate-plugin-mssql/src/backend/sql/listVariables.js @@ -0,0 +1,3 @@ +module.exports = ` + SELECT name as variable, value FROM sys.configurations ORDER BY name +`; diff --git a/plugins/dbgate-plugin-mssql/src/frontend/driver.js b/plugins/dbgate-plugin-mssql/src/frontend/driver.js index 56c315e14..fd979122e 100644 --- a/plugins/dbgate-plugin-mssql/src/frontend/driver.js +++ b/plugins/dbgate-plugin-mssql/src/frontend/driver.js @@ -116,6 +116,7 @@ const dialect = { /** @type {import('dbgate-types').EngineDriver} */ const driver = { ...driverBase, + supportsServerSummary: true, dumperClass: MsSqlDumper, dialect, readOnlySessions: false,