跳过主要内容
S

dsh-tool-database

souleymoni1/dsh-tool-database

DeepSeek Harness 数据库插件:SQL Server / PostgreSQL / MySQL 查询与执行,内置数据库面板

安装

dsh plugin --profile web add github:souleymoni1/dsh-tool-database

README

dsh-tool-database

DSH(DeepSeek Harness)数据库插件:一套 db_* 工具同时连 SQL Server / PostgreSQL / MySQL, 模型直接读(可选写)你配置的库,不经过 MCP、不起子进程;左侧栏「数据库」面板负责管连接、跑 SQL、看结果。

支持的引擎

引擎engine驱动默认端口DSN 前缀
SQL Serversqlserver(默认,兼容老清单)mssql(tedious)1433sqlserver:// / mssql:// / tds://
PostgreSQLpostgrespg5432postgres:// / postgresql:// / pg://
MySQL / MariaDBmysqlmysql23306mysql://

每个源独立选引擎;同一个插件里可以同时放 SQL Server 生产库、PostgreSQL 报表库、MySQL 业务库。

注册工具

工具功能
db_sources列出已配置的源(id / 引擎 / 主机 / 端口 / 库 / 账号 / 是否可写),可 probe: true 实测连通性
db_databases列出该实例上的数据库(SQL Server sys.databases / PostgreSQL pg_database / MySQL SHOW DATABASES)
db_tables列出表与视图(schema / 类型 / 行数估算),支持 schema / filter 过滤
db_schema单表列结构:类型(带长度精度)/ 可空 / 自增 / 主键 / 默认值
db_query只读查询,支持多条语句(逐条执行、各自成一个结果集),参数绑定只对单条生效;page + limit 控制翻页(limit = 每页行数),返回 { statements: [{ columns, rows, page, pageSize, hasNext, paged, elapsedMs }] }
db_execute写通道,需源开启 writable 且显式 allowWrite: true;DDL 另需 allowDdl

省 token 工作流:db_sources → db_tables filter: → db_schema → db_query。先看结构再取数,避免 SELECT * 全表灌进上下文。

参数占位按引擎走:SQL Server 用 @p0, @p1 …;PostgreSQL 用 $1, $2 …;MySQL 用 ?,值都放 params 数组。

左侧栏「数据库」面板(0.2.1 起在左侧栏,0.2.0 曾在会话标签页)

左侧栏全局面板区多一个 数据库(挨着「插件 / 自动化任务」),点开就是:

  • 左栏:连接列表(搜索、类型标签、引擎徽标、可写标记,宽窄可用中间分隔条左右拖动,宽度记在浏览器本地),点一条即在右侧打开;
  • 右栏 · 查询:多页签 SQL 编辑器(语法高亮 / 关键字与字段补全 / 页签与历史,见下节)+ 「执行」(Ctrl / Cmd + Enter),结果表格显示列名、行数、耗时,超限标「已截断」,状态行右侧一键复制整表;
  • 右栏 · 连接表单:新建 / 编辑连接用表单填(引擎、类型、主机、端口、库、账号、密码、TLS、可写、允许 DDL), 「测试连接」当场试连;密码框右侧的眼睛可以显示/隐藏密码(编辑已有连接时会把本机保存的密码读回框里,点眼睛就能看到原值);连接字符串收在「高级」里,不想填字段时再展开。

左侧栏入口

「数据库」面板:左连接列表 + 右查询区

新建连接表单:引擎下拉切换时端口自动跟着变,密码框带眼睛

展开「高级」可以直接贴连接字符串(填了它就忽略上面的主机表单):

高级:直接用连接字符串

类型与分组(0.3.0)

每个连接有一个类型,只有三档:开发 / 测试 / 正式(stage: dev | test | prod)。

  • 搜索框下面有 不分组 / 按类型分组 两个单选项,选择会记在浏览器本地,下次打开还是这个状态;
  • 列表每条右侧靠右排列,从右往左依次是 类型 / 数据库(引擎)/ 可写;默认按**别名(id)**排序,开了分组就先按类型(开发 → 测试 → 正式),组内再按别名排序,空分组不显示;
  • 老清单(没有 stage)读进来时按别名 / 描述 / 库名推断:含 DEV 记开发,含 TEST / QA / UAT / STAGING 记测试,其余记正式; 保存任意一条连接时,推断结果会作为 stage 写回清单固定下来,之后以清单为准。

按类型分组:开发 / 测试 / 正式,组内按别名排序

查询页签(0.3.4 起)

每个连接下面可以开多个查询页签,互相独立,页签和 SQL 都自动保存在本机($DSH_HOME/database-tool/queries.json,和 sources.json 放一起):

操作说明
+新建一个空白查询页签
点页签切到这个页签(切之前会把当前输入落盘)
页签上的 ×关闭页签:不删数据,进「历史页签」
历史页签下拉列出关闭过的页签(标题 + SQL 前 60 字),点一条原样恢复;右侧 × 才是彻底删除
双击页签标题就地改名(回车确认、Esc 取消、清空恢复按 SQL 自动命名),改名后的页签不再被 SQL 首行覆盖;重命名也会存进 queries.json(named: true)
编辑器 / 结果之间的分隔条上下拖动调整两块高度(90px ~ 底部留 170px),拖完记住位置(localStorage: dbx-editor-height),下次打开还是这个比例

页签标题取 SQL 第一行有效内容(去掉 -- 注释、超过 28 字截断),没写内容时显示「查询」。输入停顿 700ms 自动保存,关窗口/重启 DSH 后页签原样回来。

{
  "version": 1,
  "sources": {
    "local_dev": [
      { "id": "qmw94f2z6ips3", "title": "SELECT TOP 5 name FROM sys…", "sql": "SELECT TOP 5 name FROM sys.databases", "updatedAt": 1794220272601, "closed": false, "named": false }
    ]
  }
}

页签按连接(source id)分开存,切到别的连接看到的是它自己的页签。

编辑器和结果共用一块区域,中间的分隔条可以上下拖动;结果的行数/耗时靠右、复制按钮靠左,都贴在结果表格下方。

SQL 控制台(0.3.4 起,0.3.5 加多语句 / 分页 / 序号 / 列宽 / 执行选中)

输入框是「高亮层 + 透明 textarea」叠出来的,所以既有语法着色,又是原生输入(光标、选中、输入法、撤销都正常):

能力说明
语法高亮关键字 / 字符串 / 数字 / 注释四种颜色;两层字体度量锁死,光标与选中位置和看到的字严格对齐

| 补全 | 关键字 + 当前库的表名 + 当前表(FROM / JOIN 后面那张)的字段名,字段排最前并标「字段」、表名标「表」;输入 1~2 个字符自动弹,Ctrl + 空格 强制弹,↑ ↓ 选、Enter / Tab 确认、Esc 关闭,列表跟随光标并自动翻页;别名. 之后直接列该表字段 | | 复制结果 | 结果表格左下角复制图标,导出 TSV(含表头),粘到 Excel 直接分列;行数与耗时放在右下角 | | 多语句 | 一个输入框里写多条语句,按顺序逐条执行,每条一个结果集;没写分号也能识别(换行后以 SELECT/UPDATE/INSERT/… 开头即视为新语句,; 和单独一行 GO 同样支持);结果区上方出现「结果 1 / 结果 2 / 执行 3」切换条,查询和写可混在一个脚本里 | | 行号 | 结果表第一列固定是 # 序号(跟着翻页连续编号:第 2 页从 101 开始),列宽压到 34px;复制 TSV 也带这一列 | | 列宽 | 表头右侧边缘可左右拖动调列宽,# 列不参与;同样几列的结果重跑会沿用上次拖出来的宽度(刷新页面重置),列总宽超出时表格横向滚动 | | 分页 | 结果不再截断:默认每页 100 行;上一页 / 下一页、第 N 页 · 行数 · 耗时、50/100/200/500 行/页 都在结果区右下角同一行;翻页由引擎自己拼 OFFSET/FETCH(PostgreSQL / MySQL 拼 LIMIT/OFFSET),不会把整表拉回内存 | | 执行选中 | 在编辑器里选中一段 SQL,右上角按钮变成「执行已选择」,只跑选中的那一段(Ctrl / Cmd + Enter 同样只跑选中);取消选中又变回「执行」 | | 快捷键 | Ctrl / Cmd + Enter 执行(有选中就只跑选中),Tab 缩进两格 |

结果表格高度跟随窗口剩余空间、只在自己区域内滚动,页面不会整体滚动;表头 13px 加粗淡灰底并吸顶,数据 12px。 设置页里只留「数据库连接」一节:控制台的写策略与默认行数。

设置页:控制台写策略

所有改动都写回宿主侧清单文件(临时文件 + rename),宿主按 mtime 热加载,不用重启。

安装

已发布到 npm:dsh-tool-database(源码仓库:https://github.com/SouleyMoni1/dsh-tool-database )。

Web profile

dsh plugin --profile web add dsh-tool-database@0.3.5

建议带上显式版本号:npm 上还留着一个早期占位版本 0.0.0-stage(tarball 已损坏,删不掉), 不带版本号时 pnpm 有机会解析到它并报 ERR_PNPM_TARBALL_EXTRACT。

桌面端(desktop profile,由 Electron 应用独占管理)

dsh plugin --profile desktop ... 会被 CLI 直接拒绝: profile "desktop" is managed exclusively by the Electron application。 桌面端要么走市场面板装 npm 上的包,要么手工做一遍 CLI 的等价操作:

  1. ~/.dsh/profiles/desktop/package.json 的 dependencies 加 "dsh-tool-database": "^0.3.5";
  2. 同一文件的 dsh.profile.bundles 数组加 "dsh-tool-database";
  3. 在 profile 目录里用与该 profile 同大版本的 pnpm 执行安装,然后重启 DSH: 桌面 profile 当前是 pnpm 11.28.5(store 在 ~/AppData/Local/pnpm/store/v11), 用 v10 会报 “node_modules was installed with a different major version of pnpm”, 直接 cd ~/.dsh/profiles/desktop && npx --yes pnpm@11.28.5 add dsh-tool-database@0.3.5 最稳。

装完重启 DSH:6 个工具、侧栏面板、设置页标签都要重启后才出现(sources.json 的改动不用重启)。

从 dsh-tool-mssql 升级

旧的 dsh-tool-mssql 与新的 dsh-tool-database 不要同时装(会同时出现 mssql_* 和 db_* 两套工具):

dsh plugin --profile web remove dsh-tool-mssql
dsh plugin --profile web add dsh-tool-database

首次启动会自动把 $DSH_HOME/mssql-tool/sources.json 复制到 $DSH_HOME/database-tool/sources.json (只复制不删除,老清单留着随时回退);老字段 server 仍然认,缺省引擎按 sqlserver 处理。

关于入口 shim(为什么以前装进 profile 会 failed to import)

DSH 0.2.x 的 profile 层解析器(@deepseek-ai/dsh-app-boot 的 ResolutionRouter.routeScoped) 把 require('process/') 归一成裸名 process 后直接 for (const p of createRequire(parent).resolve.paths(name));Node 对内建模块名返回 null, 这段没有 ?? [] 兜底,于是抛 TypeError: createRequire.resolve.paths is not a function or its return value is not iterable。 各数据库驱动的 CJS 依赖链里都有这种写法,插件会在 import 阶段失败,启动日志只有一行 failed to import。

0.1.1 起入口改为 lib/boot.js:先加载一小段 shim,把内建模块请求直接短路(解析结果与 Node 原生一致), 再动态 import 真正实现,因此正常装进 profile 即可。宿主修好这段解析代码后,这层 shim 可以删掉。

本地目录安装(开发调试,改代码即时生效)

link: 的目标是相对 profile 目录解析的:跨盘符直接写 link:F:\... 会生成坏联接。 先在 ~/.dsh/profiles 下建一个指向仓库的目录联接,各 profile 都用相对路径引用:

mkdir "%USERPROFILE%\.dsh\profiles\.local-links"
mklink /J "%USERPROFILE%\.dsh\profiles\.local-links\dsh-tool-database" "F:\EdenOS\AI\DSH插件\dsh-tool-mssql"

link: 不跑 prepack,装之前先 npm run build 出 lib/。

dsh plugin --profile web add "link:../.local-links/dsh-tool-database"

配置

源清单两种配法,config.sources 非空时优先:

方式一:插件 config(profile 的 cordis.patch.yml)

- insert:
    - id: tool-database
      name: 'dsh-tool-database'
      config:
        defaultSource: erp_prod
        sources:
          - id: erp_prod
            engine: sqlserver
            stage: prod
            description: 【正式·只读】db.example.com/demo_erp
            host: db.example.com
            port: 1433
            database: demo_erp
            user: reader
            passwordEnv: MSSQL_PROD_PW
            writable: false
          - id: pg_report
            engine: postgres
            stage: test
            description: 【报表】pg.internal/report
            host: pg.internal
            database: report
            user: readonly
            passwordEnv: PG_REPORT_PW
            ssl: true

方式二:独立 JSON 文件(推荐,改完即时生效)

$DSH_HOME/database-tool/sources.json(默认 C:\Users\<你>\.dsh\database-tool\sources.json):

[
  {
    "id": "erp_prod",
    "engine": "sqlserver",
    "stage": "prod",
    "description": "【正式·只读】db.example.com/demo_erp",
    "host": "db.example.com",
    "port": 1433,
    "database": "demo_erp",
    "user": "reader",
    "passwordEnv": "MSSQL_PROD_PW",
    "writable": false
  },
  {
    "id": "mysql_shop",
    "engine": "mysql",
    "stage": "test",
    "host": "10.0.0.9",
    "port": 3306,
    "database": "shop",
    "user": "reader",
    "password": "仅本机可见的明文密码",
    "writable": false
  }
]

文件按 mtime 热加载:改完不用重启,下一次工具调用即生效。插件启动时若清单文件不存在也不报错,只是没有可用源。 日常维护直接用左侧栏的「数据库」面板,不用手写 JSON。

字段

字段必填说明
id✅源句柄,模型用它在各工具里选库;清单内不可重复
enginesqlserver(默认)/ postgres / mysql
stage类型:dev 开发 / test 测试 / prod 正式(默认;不写时按别名推断,见「类型与分组」)
host✅主机名或 IP(老字段名 server 仍然认)
port默认按引擎:1433 / 5432 / 3306
database默认库;不填则由账号默认库决定(MySQL 建议填)
user登录名
passwordEnv推荐:环境变量名,密码从 process.env 取
password备选:明文写在配置里(仍只在宿主侧,但会落盘)
writable默认 false。只有 true 才允许 db_execute
allowDdl默认 false。允许 CREATE/ALTER/DROP/TRUNCATE
allowBatch默认 true。写通道允许分号分隔的批量语句;显式 false 锁成单条
ssl默认 false。PostgreSQL / MySQL 走 TLS;SQL Server 等价于 encrypt
encryptSQL Server 专用;ssl: true 会一起打开
trustServerCertificate默认 true;云库用自签证书时保留 true
requestTimeoutMs单语句超时,默认 15000

密码用环境变量时要让 DSH 进程能读到(桌面端可在启动前设置系统环境变量,或改用 password)。

控制台写策略

侧栏「数据库」面板里跑 SQL 时,写语句受两层控制:

  1. 控制台写策略(设置 → 数据库连接,或 $DSH_HOME/database-tool/config.json 的 writeMode):
    • source(默认):跟随数据源的 writable / allowDdl;
    • readonly:一律只读,写语句直接拒绝(排查时最稳);
    • always:允许写(仍然要过单语句 / 提权关键字检查)。
  2. 数据源开关:源的 writable、allowDdl、allowBatch。

模型工具 db_execute 不受 writeMode 影响(它有自己的 writable + allowWrite 双闸门), 控制台策略只约束人在界面里敲的 SQL。

安全模型

  • 只读白名单:只读通道仅放行以 SELECT / WITH / VALUES 开头的语句;
  • 危险词拦截:SELECT ... INTO、EXEC、OPENROWSET、DBCC、WAITFOR、DDL/DML 关键字直接拒绝 (判定前先剥离字符串、注释与 [] / "" / 反引号标识符,不会误伤字面量里的关键字);
  • 逐条校验:; 分隔的多条语句会先逐条过白名单 / 禁词 / 类别判定,任意一条不合规整段拒绝(不会只看第一条);查询和写可以混在一个脚本里,写语句照样受 writable / writeMode / allowDdl 约束;
  • 写通道双闸门:源必须 writable: true,调用方还要显式 allowWrite: true;DDL 另需源开启 allowDdl; xp_* / OPENROWSET / BACKUP / GRANT 等提权关键字一律拒绝;
  • 参数绑定:db_query / db_execute 用引擎各自的占位符 + params 数组绑定,不做字符串拼接;
  • 输出预算:默认 100 行、硬上限 500 行,超限明确标注 truncated;
  • 凭据边界:db_sources 只输出「是否已配密码」,不含密码、不含 passwordEnv 的取值、不含完整连接串; 设置页列表里的 DSN 恒为 ******,只有本机同源、经 DSH 会话鉴权的编辑表单才拿得到明文回填。

使用示例

db_sources probe: true
db_tables source: "prod_WMS" filter: "Order"
db_schema source: "prod_WMS" table: "dbo.Sys_Log"
db_query source: "prod_WMS" sql: "SELECT TOP 10 Url, CreateTime FROM Sys_Log WHERE CreateTime >= @p0 ORDER BY CreateTime DESC" params: ["2026-01-01"]
db_query source: "pg_report" sql: "SELECT * FROM orders WHERE created_at >= $1 LIMIT 20" params: ["2026-01-01"]
db_query source: "mysql_shop" sql: "SELECT id, name FROM goods WHERE id = ?" params: [42]

开发

npm install
npm run check   # typecheck + vitest + tsc 构建
  • src/core.ts —— 纯函数:引擎元数据、源清单校验、类型格式化、凭据解析、路径约定;
  • src/sql-guard.ts —— 方言无关的 SQL 护栏(白名单 / 单语句 / 写闸门 / 提权禁词,全部可单测);
  • src/engines/{sqlserver,postgres,mysql}.ts —— 各引擎适配器(连接、查询、写、元数据);
  • src/pool.ts —— 连接池缓存与统一执行层;
  • src/dsn.ts —— 连接字符串 ⇄ 源配置(三种 scheme + ADO 写法 + 掩码);
  • src/settings-store.ts —— sources.json / config.json 的原子读写、增删改、老清单迁移;
  • src/index.ts —— 插件入口,注册 6 个工具;
  • src/settings-rpc.ts —— 面板 / 设置页的宿主侧 RPC(sources/* + query/run + console/save);
  • client/client.js —— 浏览器侧单文件客户端(侧栏面板 + 设置页节,无构建步骤);
  • tests/ —— vitest:SQL 守卫、清单校验、连接字符串、控制台配置、迁移。

已知限制

  • 批量写不开事务:多条写语句按顺序逐条提交,中途报错前面的不会回滚(需要原子性请自己包 BEGIN TRAN / COMMIT);
  • 无分号切分是启发式:按「行首语句关键字」判断新语句,括号未闭合 / 上一行以逗号、运算符、UNION 结尾时不会切;复杂脚本建议写 ;;
  • TOP / DISTINCT / UNION 不能翻页:这几种语句拼不了 OFFSET,只显示当前页并提示原因,加 WHERE 或改写后再取;
  • 翻页顺序:语句本身没写 ORDER BY 时补的是 ORDER BY (SELECT NULL),只保证取到不同行,不保证跨页稳定顺序,介意就自己写 ORDER BY;
  • 元数据查询依赖各引擎的系统目录视图,账号若无元数据可见性权限会返回空列表;
  • 连接池按「引擎 + 源 id + 主机 + 端口 + 库 + 账号」缓存,改这几项后要重启 DSH 才换池 (改 sources.json 的密码/开关不影响已建立的池);
  • ssl: false 时流量不加密,跨公网请打开 TLS。

许可

MIT

相关插件