dsh-db-tool 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/adapters/gaussdb/index.js +14 -2
- package/dist/adapters/sql-shared/pg-like.js +20 -14
- package/dist/index.js +3 -1
- package/dist/manager.js +2 -2
- package/dist/script/runner.js +5 -3
- package/dist/script/worker.cjs +3 -3
- package/docs/architecture.md +154 -0
- package/docs/install.md +2 -0
- package/package.json +1 -1
- package/skills/db-admin/SKILL.md +13 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ dsh plugin --profile web add "dsh-db-tool@github:mengqi1436/dsh-db-tool"
|
|
|
36
36
|
dsh plugin --profile web add "link:E:\path\to\dsh-db-tool"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
GaussDB 官方驱动未发布 npm,需先构建 vendor:`npm run build:gaussdb`(PowerShell)或 `bash scripts/build-gaussdb.sh
|
|
39
|
+
GaussDB 官方驱动未发布 npm,需先构建 vendor:`npm run build:gaussdb`(PowerShell)或 `bash scripts/build-gaussdb.sh`;运行要求 Node ≥ 22.12(产物依赖 p-limit@7 纯 ESM)。oracledb 安装脚本需 `npm approve-scripts oracledb`。详见 [docs/install.md](docs/install.md)。
|
|
40
40
|
|
|
41
41
|
## 安全模型
|
|
42
42
|
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GaussDB(openGauss)适配器。
|
|
3
3
|
*
|
|
4
|
-
* ⚠️ 官方驱动 openGauss-connector-nodejs 未发布 npm
|
|
5
|
-
*
|
|
4
|
+
* ⚠️ 官方驱动 openGauss-connector-nodejs 未发布 npm(华为云 HCS 26.861.0 官方文档
|
|
5
|
+
* 应用程序接口清单仅 JDBC/ODBC/libpq/Psycopg/Go/ECPG,无 Node 驱动),Node 接入基于
|
|
6
|
+
* PostgreSQL 协议兼容自行验证。使用 vendor/gaussdb-pg 构建产物(fork 自 pg 8.6.0,
|
|
7
|
+
* API 与 pg 完全兼容),未真机验证。
|
|
8
|
+
*
|
|
9
|
+
* 已按官方文档对齐(证据见 skills/db-admin/SKILL.md GaussDB 节):
|
|
10
|
+
* - 认证:驱动实现 openGauss SHA256 / MD5-SHA256 / SM3 握手(vendor pg-protocol parser.ts:335-357、
|
|
11
|
+
* rfc5802.js:44),对应服务端 password_encryption_type 默认 2 (sha256);
|
|
12
|
+
* - 默认端口 8000(集中式 DN / 分布式 CN)、ro 会话 `SET SESSION CHARACTERISTICS AS
|
|
13
|
+
* TRANSACTION READ ONLY` 两形态官方支持(rf-dist/gaussdb-08-0400、rf-cent/gaussdb-38-0416);
|
|
14
|
+
* - 已知限制:SERIALIZABLE 功能不支持(等价 REPEATABLE READ,与 PG 的 SSI 行为不同);
|
|
15
|
+
* SSL 仅布尔开关(不支持 sslmode require/verify-ca/verify-full 细分);
|
|
16
|
+
* information_schema.tables/columns 集中式有官方视图文档、分布式参考无原生视图文档
|
|
17
|
+
* (仅 M-Compatibility 模式),跨库浏览在分布式实例上以真机行为为准。
|
|
6
18
|
*
|
|
7
19
|
* 构建方式:bash scripts/build-gaussdb.sh(或 npm run build:gaussdb)
|
|
8
20
|
* 核心逻辑与 postgresql 适配器共享(sql-shared/pg-like.ts)。
|
|
@@ -10,9 +10,13 @@ function poolConfig(conn) {
|
|
|
10
10
|
}
|
|
11
11
|
else if (conn.fields) {
|
|
12
12
|
const f = conn.fields;
|
|
13
|
+
// 兜底默认值按 kind 区分(仅表单字段被清空时触发):GaussDB 官方默认端口 8000
|
|
14
|
+
// (华为云 HCS 26.861.0:集中式 DN 与分布式 CN 均为 8000,devg-cent/gaussdb-42-0020、
|
|
15
|
+
// devg-dist/gaussdb-12-0319)、默认管理用户 gaussdb;postgresql 维持社区默认 5432/postgres 不变。
|
|
16
|
+
const gb = conn.meta.kind === 'gaussdb';
|
|
13
17
|
base.host = String(f.host ?? '127.0.0.1');
|
|
14
|
-
base.port = Number(f.port ?? 5432);
|
|
15
|
-
base.user = String(f.user ?? f.username ?? 'postgres');
|
|
18
|
+
base.port = Number(f.port ?? (gb ? 8000 : 5432));
|
|
19
|
+
base.user = String(f.user ?? f.username ?? (gb ? 'gaussdb' : 'postgres'));
|
|
16
20
|
if (f.password != null)
|
|
17
21
|
base.password = String(f.password);
|
|
18
22
|
if (f.database != null)
|
|
@@ -28,20 +32,23 @@ function poolConfig(conn) {
|
|
|
28
32
|
export async function createPgLikeAdapter(kind, Driver, conn, opts) {
|
|
29
33
|
const pool = new Driver.Pool(poolConfig(conn));
|
|
30
34
|
const readOnly = opts?.mode === 'ro';
|
|
31
|
-
//
|
|
35
|
+
// 所有池(主池 + 跨库池)统一走此初始化。
|
|
36
|
+
// pg 约定:release(err) 若无等待者会 emit pool 'error',无监听器会崩进程——
|
|
37
|
+
// 官方 Pool 文档要求必须注册 error 监听(空闲连接因后端故障销毁时经此冒泡),无条件兜底。
|
|
38
|
+
// 服务器级 ro 强制(官方手段):每个新连接会话设为只读事务,仅 ro 模式注册。
|
|
32
39
|
// fail-closed:SET 失败时 release(err) 让驱动销毁该连接、等待的 acquire 收到错误——
|
|
33
40
|
// 会话级只读是 ro 的最后防线,不允许静默降级成可写连接。
|
|
34
|
-
const
|
|
35
|
-
p.on('connect', (c) => {
|
|
36
|
-
void c.query('SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY').catch((err) => {
|
|
37
|
-
c.release(err instanceof Error ? err : new Error(String(err)));
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
// pg 约定:release(err) 若无等待者会 emit pool 'error',不监听会崩进程
|
|
41
|
+
const setupPool = (p) => {
|
|
41
42
|
p.on('error', () => { });
|
|
43
|
+
if (readOnly) {
|
|
44
|
+
p.on('connect', (c) => {
|
|
45
|
+
void c.query('SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY').catch((err) => {
|
|
46
|
+
c.release(err instanceof Error ? err : new Error(String(err)));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
42
50
|
};
|
|
43
|
-
|
|
44
|
-
setupReadOnly(pool);
|
|
51
|
+
setupPool(pool);
|
|
45
52
|
// 事务激活期间所有 query/execute 路由到同一 client
|
|
46
53
|
let txClient = null;
|
|
47
54
|
const run = (sql, params) => txClient ? txClient.query(sql, params) : pool.query(sql, params);
|
|
@@ -67,8 +74,7 @@ export async function createPgLikeAdapter(kind, Driver, conn, opts) {
|
|
|
67
74
|
if (cached)
|
|
68
75
|
return cached;
|
|
69
76
|
const created = new Driver.Pool({ ...poolConfig(conn), database: db });
|
|
70
|
-
|
|
71
|
-
setupReadOnly(created);
|
|
77
|
+
setupPool(created); // 与主池一致:error 兜底 + ro 会话只读
|
|
72
78
|
dbPools.set(db, created);
|
|
73
79
|
return created;
|
|
74
80
|
};
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,9 @@ action 说明:
|
|
|
30
30
|
- preview:预览行,limit≤50(conn_id, table, database?, limit?)。
|
|
31
31
|
- run_script:子进程沙箱脚本(conn_id, code),60s 超时强杀,permission model 禁文件
|
|
32
32
|
访问 + 新 vm realm 双层隔离,仅注入受限 db.query/db.execute 句柄(经完整
|
|
33
|
-
guard/审计链路),rw
|
|
33
|
+
guard/审计链路),rw 连接才有写能力。句柄签名 db.query(sql, params?, database?):
|
|
34
|
+
第三参为跨库路由目标(pg/gaussdb 等按库路由,同 Navicat 式),多库统计在脚本内
|
|
35
|
+
循环逐库调用即可一次完成。`;
|
|
34
36
|
export function apply(ctx) {
|
|
35
37
|
const log = ctx.logger ?? { info: () => { }, error: () => { } };
|
|
36
38
|
const store = new DbToolStore();
|
package/dist/manager.js
CHANGED
|
@@ -249,8 +249,8 @@ export class DbToolService {
|
|
|
249
249
|
try {
|
|
250
250
|
const result = await runScriptInChild({
|
|
251
251
|
code: src,
|
|
252
|
-
dbQuery: async (sql, params) => this.unwrapForScript(await this.query(key, connId, sql, params, challengeId)),
|
|
253
|
-
dbExecute: async (statement, params) => this.unwrapForScript(await this.execute(key, connId, statement, params, challengeId)),
|
|
252
|
+
dbQuery: async (sql, params, database) => this.unwrapForScript(await this.query(key, connId, sql, params, challengeId, database)),
|
|
253
|
+
dbExecute: async (statement, params, database) => this.unwrapForScript(await this.execute(key, connId, statement, params, challengeId, database)),
|
|
254
254
|
onLog: (level, text) => level === 'error' ? console.error('[db-script]', text) : console.log('[db-script]', text),
|
|
255
255
|
onTimeout: () => {
|
|
256
256
|
void sessionAdapter.close().catch(() => { });
|
package/dist/script/runner.js
CHANGED
|
@@ -118,11 +118,13 @@ export async function runScriptInChild(opts) {
|
|
|
118
118
|
});
|
|
119
119
|
});
|
|
120
120
|
async function handleDbCall(method, args) {
|
|
121
|
-
const [statement, params] = args;
|
|
121
|
+
const [statement, params, rawDatabase] = args;
|
|
122
|
+
// IPC JSON 序列化会把 undefined 变 null,归一回 undefined 保持与直连调用语义一致
|
|
123
|
+
const database = rawDatabase ?? undefined;
|
|
122
124
|
if (method === 'query')
|
|
123
|
-
return opts.dbQuery(statement, params);
|
|
125
|
+
return opts.dbQuery(statement, params, database);
|
|
124
126
|
if (method === 'execute')
|
|
125
|
-
return opts.dbExecute(statement, params);
|
|
127
|
+
return opts.dbExecute(statement, params, database);
|
|
126
128
|
throw new DbToolError('INVALID_ARGUMENT', `未知 db 方法: ${method}`);
|
|
127
129
|
}
|
|
128
130
|
function errorOf(e) {
|
package/dist/script/worker.cjs
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* IPC 协议:
|
|
12
12
|
* 父→worker {type:'run', code}
|
|
13
|
-
* worker→父 {type:'db', reqId, method, args}
|
|
13
|
+
* worker→父 {type:'db', reqId, method, args} // args=[statement, params, database?],database 即跨库路由目标
|
|
14
14
|
* 父→worker {type:'dbResult', reqId, ok, result, error}
|
|
15
15
|
* worker→父 {type:'done', ok, result, error}
|
|
16
16
|
*/
|
|
@@ -28,11 +28,11 @@ async function runScript(code) {
|
|
|
28
28
|
const pending = new Map();
|
|
29
29
|
let reqSeq = 0;
|
|
30
30
|
|
|
31
|
-
const dbCall = (method) => (statement, params) =>
|
|
31
|
+
const dbCall = (method) => (statement, params, database) =>
|
|
32
32
|
new Promise((resolve, reject) => {
|
|
33
33
|
const reqId = ++reqSeq;
|
|
34
34
|
pending.set(reqId, { resolve, reject });
|
|
35
|
-
process.send({ type: 'db', reqId, method, args: [statement, params] });
|
|
35
|
+
process.send({ type: 'db', reqId, method, args: [statement, params, database] });
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
const db = {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# dsh-db-tool 项目架构图
|
|
2
|
+
|
|
3
|
+
> 由 cbm(codebase-memory)索引数据绘制:843 节点 / 2702 边,模块分层见各图。
|
|
4
|
+
> 索引项目名:`E-Code-dsh-dsh-db-tool`。
|
|
5
|
+
|
|
6
|
+
## 1. 总体分层架构
|
|
7
|
+
|
|
8
|
+
```mermaid
|
|
9
|
+
flowchart TB
|
|
10
|
+
subgraph UI["客户端层(DSH 侧边栏)"]
|
|
11
|
+
CLIENT["client/client.js<br/>连接管理 · 对象树浏览 · SQL 控制台 · 授权面板"]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subgraph API["接入层"]
|
|
15
|
+
HTTP["lib/http<br/>HTTP API(13 条路由)"]
|
|
16
|
+
TOOL["lib/index.ts<br/>DatabaseManager 工具定义<br/>list_connections / query / execute /<br/>schema / preview / run_script"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
subgraph SVC["服务编排层"]
|
|
20
|
+
MGR["lib/manager.ts<br/>ro/rw 项目授权校验 · 适配器生命周期 · 事务编排"]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
subgraph SEC["安全层"]
|
|
24
|
+
GUARD["lib/guard<br/>SQL/命令分类 · 危险操作识别 ·<br/>一次性 challenge 确认(5 分钟有效)"]
|
|
25
|
+
STORE["lib/store<br/>connections · grants · secrets(脱敏)·<br/>audit 审计 · normalize · io"]
|
|
26
|
+
SCRIPT["lib/script<br/>runner.ts + worker.cjs<br/>子进程沙箱(vm realm · 禁文件 · 60s 超时)"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
subgraph ADPT["适配器层 lib/adapters(8 库)"]
|
|
30
|
+
REG["index.ts<br/>kind → 工厂注册表 + driverMissingError"]
|
|
31
|
+
SQLSHARED["sql-shared/<br/>common.ts(标识符/分页/规范化)<br/>pg-like.ts(PostgreSQL + GaussDB 共享)"]
|
|
32
|
+
A1["mysql"]
|
|
33
|
+
A2["postgresql"]
|
|
34
|
+
A3["gaussdb<br/>vendor/gaussdb-pg 驱动加载"]
|
|
35
|
+
A4["sqlite"]
|
|
36
|
+
A5["redis"]
|
|
37
|
+
A6["mongodb"]
|
|
38
|
+
A7["oracle"]
|
|
39
|
+
A8["dmdb"]
|
|
40
|
+
TYPES["types.ts<br/>DatabaseAdapter 契约"]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
subgraph DRV["驱动层"]
|
|
44
|
+
D1["pg / mysql2 / sqlite3 / redis<br/>mongodb / oracledb / dmdb"]
|
|
45
|
+
D2["vendor/gaussdb-pg<br/>openGauss-connector-nodejs 构建产物"]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
CLIENT -->|HTTP| HTTP
|
|
49
|
+
CLIENT -.->|注入| TOOL
|
|
50
|
+
TOOL --> MGR
|
|
51
|
+
MGR --> GUARD
|
|
52
|
+
MGR --> STORE
|
|
53
|
+
MGR --> SCRIPT
|
|
54
|
+
MGR --> REG
|
|
55
|
+
REG --> SQLSHARED
|
|
56
|
+
REG --> A1 & A4 & A5 & A6 & A7 & A8
|
|
57
|
+
A2 --> SQLSHARED
|
|
58
|
+
A3 --> SQLSHARED
|
|
59
|
+
SQLSHARED --> TYPES
|
|
60
|
+
A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8 -.-> DRV
|
|
61
|
+
SCRIPT -.->|db.query / db.execute 经完整 guard 链路| MGR
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 2. 请求时序(query 与危险操作确认流)
|
|
65
|
+
|
|
66
|
+
```mermaid
|
|
67
|
+
sequenceDiagram
|
|
68
|
+
autonumber
|
|
69
|
+
participant U as 用户(聊天)
|
|
70
|
+
participant T as DatabaseManager 工具
|
|
71
|
+
participant M as lib/manager.ts
|
|
72
|
+
participant G as lib/guard
|
|
73
|
+
participant S as lib/store
|
|
74
|
+
participant A as 适配器(8 库)
|
|
75
|
+
participant DB as 数据库
|
|
76
|
+
|
|
77
|
+
U->>T: query/execute(conn_id, sql)
|
|
78
|
+
T->>S: 授权校验(项目路径 → 连接 → ro/rw)
|
|
79
|
+
alt 未授权
|
|
80
|
+
S-->>T: UNAUTHORIZED_PROJECT
|
|
81
|
+
else ro 授权 + 写操作
|
|
82
|
+
S-->>T: READ_ONLY(拒绝)
|
|
83
|
+
else 通过
|
|
84
|
+
T->>G: 语句分类
|
|
85
|
+
alt 危险操作(DDL/DML/维护命令)
|
|
86
|
+
G-->>T: NEEDS_CONFIRMATION + challengeId(一次性,5 分钟)
|
|
87
|
+
T-->>U: 说明语句与风险,等待明确同意
|
|
88
|
+
U->>T: 携同一 challengeId 重试
|
|
89
|
+
T->>G: 校验 challenge(绑定语句 hash)
|
|
90
|
+
end
|
|
91
|
+
T->>M: 执行
|
|
92
|
+
M->>A: query/execute(可选 database 跨库路由,pg/gaussdb)
|
|
93
|
+
A->>DB: 参数化 SQL(ro 会话级 READ ONLY 双保险)
|
|
94
|
+
DB-->>A: 结果
|
|
95
|
+
A-->>T: 规范化结果(DECIMAL→string 等)
|
|
96
|
+
T->>S: 审计记录
|
|
97
|
+
T-->>U: {columns, rows, rowCount} / {affectedRows, message}
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 3. 适配器体系(8 库 × 共享实现)
|
|
102
|
+
|
|
103
|
+
```mermaid
|
|
104
|
+
flowchart LR
|
|
105
|
+
subgraph 契约
|
|
106
|
+
T["types.ts<br/>DatabaseAdapter / TableInfo / ColumnInfo<br/>DbKind = 8 种"]
|
|
107
|
+
end
|
|
108
|
+
subgraph 工厂注册
|
|
109
|
+
R["adapters/index.ts<br/>kind → lazy import 工厂<br/>缺失驱动 → driverMissingError(附构建提示)"]
|
|
110
|
+
end
|
|
111
|
+
subgraph SQL系共享
|
|
112
|
+
PG["pg-like.ts<br/>PostgreSQL + GaussDB<br/>pool · ro 会话 · 跨库路由 ·<br/>库→schema→表 三层浏览"]
|
|
113
|
+
CM["common.ts<br/>assertIdent · quoteIdent<br/>clampLimit/Offset · normalizeCell"]
|
|
114
|
+
end
|
|
115
|
+
subgraph 独立实现
|
|
116
|
+
MY["mysql"]
|
|
117
|
+
SQ["sqlite"]
|
|
118
|
+
RD["redis(SCAN 禁 KEYS)"]
|
|
119
|
+
MG["mongodb(强制显式 filter)"]
|
|
120
|
+
OR["oracle"]
|
|
121
|
+
DM["dmdb"]
|
|
122
|
+
end
|
|
123
|
+
PG --> CM
|
|
124
|
+
MY & SQ & RD & MG & OR & DM -.-> CM
|
|
125
|
+
R --> PG & MY & SQ & RD & MG & OR & DM
|
|
126
|
+
PG -.->|"gaussdb 差异仅驱动加载<br/>createRequire vendor/gaussdb-pg"| G["gaussdb/index.ts"]
|
|
127
|
+
T --- R
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 4. 模块分层职责(cbm layers 数据)
|
|
131
|
+
|
|
132
|
+
| 层 | 模块 | 特征 |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| entry | lib、script、e2e-mock | 仅出边(调用下游) |
|
|
135
|
+
| api | http | 含 13 条 HTTP 路由定义 |
|
|
136
|
+
| core | adapters(4 入 0 出)、store(12 入 0 出) | 高扇入核心,不依赖上层 |
|
|
137
|
+
| internal | manager(7 入 12 出)、tool、http | 编排枢纽 |
|
|
138
|
+
| leaf | guard | 仅入边,纯分类/判定 |
|
|
139
|
+
|
|
140
|
+
## 5. GaussDB 专项链路
|
|
141
|
+
|
|
142
|
+
```mermaid
|
|
143
|
+
flowchart TB
|
|
144
|
+
T["DatabaseManager(query/execute/schema/preview, database=...)"] --> M["manager"]
|
|
145
|
+
M --> A3["gaussdb/index.ts<br/>loadGaussDriver():createRequire<br/>vendor/gaussdb-pg/packages/pg(CJS)"]
|
|
146
|
+
A3 --> PL["sql-shared/pg-like.ts<br/>kind='gaussdb'"]
|
|
147
|
+
PL -->|poolConfig:host/port 8000/user/password/database/ssl| P["PgLikePool"]
|
|
148
|
+
PL -->|database 参数| PF["poolFor(db):按库缓存池(Navicat 式跨库)"]
|
|
149
|
+
PL -->|ro 模式| SRO["每个新连接 SET SESSION CHARACTERISTICS<br/>AS TRANSACTION READ ONLY(fail-closed)"]
|
|
150
|
+
P --> DB[("GaussDB 服务端<br/>openGauss 协议")]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- 驱动构建:`scripts/build-gaussdb.sh` / `.ps1` → 克隆 openGauss-connector-nodejs → `vendor/gaussdb-pg/packages/pg`(gitignore)。
|
|
154
|
+
- 测试:`tests/adapters-sql/gaussdb.test.ts`(驱动加载/工厂,mock 离线)+ `pg-like.test.ts`(pg/gaussdb 共享行为)。
|
package/docs/install.md
CHANGED
|
@@ -43,6 +43,8 @@ rm -rf ../gaussdb-pg && cp -r packages/pg ../gaussdb-pg
|
|
|
43
43
|
|
|
44
44
|
产物为 `vendor/gaussdb-pg`(CJS,结构同 `pg`:`{ Pool, Client, ... }`)。
|
|
45
45
|
|
|
46
|
+
> **Node 版本要求**:≥ 22.12。构建脚本会补装 `p-limit@7`(纯 ESM,源码 package.json 未声明),依赖 Node 原生 require(esm);更旧 Node 加载 GaussDB 驱动会抛 `ERR_REQUIRE_ESM`(其余 7 库不受影响)。
|
|
47
|
+
|
|
46
48
|
## oracledb approve-scripts
|
|
47
49
|
|
|
48
50
|
`oracledb` 安装时需要运行安装脚本编译/下载二进制。仓库 `package.json` 已配置白名单:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-db-tool",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "DSH community plugin: chat-operated multi-database admin tool with sidebar management, project-scoped grants, ro/rw modes and dangerous-operation confirmation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/skills/db-admin/SKILL.md
CHANGED
|
@@ -99,7 +99,7 @@ DatabaseManager({ action: "run_script", conn_id: "mongo1", code: '{"find":"users
|
|
|
99
99
|
|---|---|---|---|---|
|
|
100
100
|
| MySQL | `?` | `information_schema` | `LIMIT n OFFSET m` | |
|
|
101
101
|
| PostgreSQL | `$1, $2…` | `information_schema` / `pg_catalog` | `LIMIT n OFFSET m` | |
|
|
102
|
-
| GaussDB | `$1, $2…` | `information_schema` / `pg_catalog` | `LIMIT n OFFSET m` | PG
|
|
102
|
+
| GaussDB | `$1, $2…` | `information_schema` / `pg_catalog` | `LIMIT n OFFSET m` | PG 系(默认端口 8000,见下方注记) |
|
|
103
103
|
| SQLite | `?` | `sqlite_master` / `PRAGMA` | `LIMIT n OFFSET m` | 库列表固定 `['main']` |
|
|
104
104
|
| Redis | 无(命令数组) | `SCAN`(禁用 `KEYS` 遍历) | `SCAN cursor` | `run_script` 传 `["SCAN","0","MATCH","user:*","COUNT","100"]` |
|
|
105
105
|
| MongoDB | 无(BSON 文档) | `listCollections` | `find().skip().limit()` | `run_script` 传 `{"find":"users","filter":{},"limit":20,"skip":40}` |
|
|
@@ -108,6 +108,18 @@ DatabaseManager({ action: "run_script", conn_id: "mongo1", code: '{"find":"users
|
|
|
108
108
|
|
|
109
109
|
**类型规范化**(工具返回值已自动处理,引用结果时注意):`DECIMAL/NUMERIC` → string(避免精度丢失);`Date/TIMESTAMP` → ISO 8601 string;`LOB/CLOB/BLOB` → string;MongoDB `ObjectId` → string。生成写语句时,DECIMAL 直接传字符串值、日期传 ISO 字符串即可。
|
|
110
110
|
|
|
111
|
+
## GaussDB 官方对齐注记(HCS 26.861.0,集中式/分布式)
|
|
112
|
+
|
|
113
|
+
依据华为云 GaussDB 官方文档(doc.hcs.huawei.com/db/zh-cn,26.861.0 双形态)与 openGauss 官方文档源仓库对齐;未真机验证处以代码内标注为准。
|
|
114
|
+
|
|
115
|
+
- **认证**:驱动实现 openGauss SHA256 / MD5-SHA256 / SM3 握手,匹配服务端默认 `password_encryption_type = 2`(sha256)。连接报 `Invalid username/password, login denied` 时依次排查:① 认证配置(gs_hba.conf)需含 `host all all 0.0.0.0/0 sha256`;② 服务端密码加密方式变更后必须重设密码或新建用户(旧口令仍是旧加密);③ 账号锁定用 `ALTER USER ... ACCOUNT UNLOCK`。
|
|
116
|
+
- **默认端口 8000**(集中式 DN / 分布式 CN,官方 gsql 示例 `-p 8000`);SSL 默认不强制(服务端可 require_ssl 强制)。本工具 SSL 仅开/关,**不支持** sslmode(require/verify-ca/verify-full)证书校验细分。
|
|
117
|
+
- **ro 只读会话**:`SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY` 为官方语法(集中式/分布式均支持,rf-dist/gaussdb-08-0400、rf-cent/gaussdb-38-0416),连接建立时执行一次即对该连接所有后续事务生效。
|
|
118
|
+
- **隔离级别差异**:READ UNCOMMITTED 等价 READ COMMITTED;**SERIALIZABLE 功能不支持,等价 REPEATABLE READ**——与 PG 真 SSI 行为不同,依赖 PG 串行化语义的脚本注意。
|
|
119
|
+
- **元数据**:`pg_database` / `pg_catalog.pg_namespace` 为官方系统表;`information_schema.tables/columns` 集中式有官方视图文档,分布式参考无原生视图(仅 M-Compatibility 模式有),分布式实例上浏览以真机行为为准。
|
|
120
|
+
- **兼容模式**:openGauss 有 sql_compatibility(A/B/C/PG)兼容模式,部分语法语义随模式变化(如 B 模式 SET SESSION TRANSACTION 需 `b_format_behavior_compat_options` 含 set_session_transaction 才生效),本工具按 PG 语义使用。
|
|
121
|
+
- 驱动/默认值差异的代码内证据与证据 URL 见 `lib/adapters/gaussdb/index.ts` 头注释与 `lib/adapters/sql-shared/pg-like.ts`。
|
|
122
|
+
|
|
111
123
|
## 危险操作确认流程(NEEDS_CONFIRMATION)
|
|
112
124
|
|
|
113
125
|
收到形如以下的返回时:
|