This commit is contained in:
dengqichen 2025-11-15 17:29:54 +08:00
parent cd7788de95
commit 23a7f0cd81

420
DM_AUTOMATION_RESEARCH.md Normal file
View File

@ -0,0 +1,420 @@
# 达梦数据库自动化执行方案研究报告
## 📋 调研总结
### 一、达梦官方提供的工具和接口
#### 1. **disql命令行工具** ⭐ 推荐
**位置**: `D:\sortware\dm_manager\bin\disql.exe`
**功能**:
- 达梦官方命令行SQL执行工具
- 类似Oracle的sqlplus
- 支持批量执行SQL文件
- 支持脚本参数传递
**命令格式**:
```bash
# 基本连接
disql SYSDBA/password@host:port
# 执行SQL文件
disql SYSDBA/password@host:port @file.sql
# 直接执行SQL
disql SYSDBA/password@host:port -E "SQL语句"
# 批处理模式(静默)
disql -S SYSDBA/password@host:port @file.sql
```
**优点**:
- ✅ 官方工具,最稳定可靠
- ✅ 无需额外依赖
- ✅ 支持所有SQL语法
- ✅ 可以在批处理脚本中调用
**缺点**:
- ❌ 输出解析较麻烦
- ❌ 错误处理不够灵活
---
#### 2. **JDBC驱动** ⭐⭐ 高度推荐
**位置**: `D:\sortware\dm_manager\drivers\jdbc\DmJdbcDriver8.jar`
**驱动类**: `dm.jdbc.driver.DmDriver`
**连接URL格式**:
```
jdbc:dm://host:port
jdbc:dm://219.142.42.183:5256
```
**Java示例**:
```java
Class.forName("dm.jdbc.driver.DmDriver");
Connection conn = DriverManager.getConnection(
"jdbc:dm://219.142.42.183:5256",
"SYSDBA",
"@1sdgCq456"
);
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE ...");
conn.commit();
```
**Node.js调用Java方式**:
- 使用`child_process.spawn()`执行Java程序
- 通过标准输入/输出通信
- 获取执行结果和错误信息
**优点**:
- ✅ 功能强大,完全控制
- ✅ 支持事务、批处理
- ✅ 错误处理完善
- ✅ 可以获取详细执行结果
**缺点**:
- ❌ 需要Java环境
- ❌ 需要编译Java代码
---
#### 3. **Node.js驱动 (dmdb)** ⭐⭐⭐ 最推荐
**官方npm包**: `dmdb`
**安装**:
```bash
npm install dmdb
```
**基本使用**:
```javascript
const dmdb = require('dmdb');
// 创建连接
const conn = await dmdb.createConnection({
connectString: 'dm://SYSDBA:@1sdgCq456@219.142.42.183:5256',
autoCommit: false
});
// 执行SQL
await conn.execute('CREATE TABLE ...');
await conn.commit();
await conn.close();
```
**连接字符串格式**:
```
dm://username:password@host:port?autoCommit=false&schema=SCHEMA_NAME
```
**优点**:
- ✅ **原生Node.js支持**
- ✅ 完美集成到我们的工具中
- ✅ Promise/async支持
- ✅ 连接池支持
- ✅ 错误处理完善
- ✅ 无需编译,直接使用
**缺点**:
- ❌ 需要安装dmdb包可能需要C++编译环境)
---
## 二、推荐的自动化方案
### 🏆 方案A: Node.js + dmdb驱动最佳方案
**优势**: 完全原生Node.js与现有converter.js完美集成
**实现步骤**:
1. 安装dmdb驱动
2. 修改现有的auto-executor.js使用dmdb
3. 实现连接池和批量执行
**架构**:
```
converter.js (转换SQL)
output/*_dm.sql (转换后的SQL)
auto-executor-dmdb.js (使用dmdb执行)
达梦数据库 (5256端口)
```
**代码示例**:
```javascript
const dmdb = require('dmdb');
const fs = require('fs');
async function executeSQL(host, port, user, password, sqlFile) {
const conn = await dmdb.createConnection({
connectString: `dm://${user}:${password}@${host}:${port}`,
autoCommit: false
});
const sql = fs.readFileSync(sqlFile, 'utf8');
const statements = sql.split(';').filter(s => s.trim());
for (const stmt of statements) {
try {
await conn.execute(stmt);
} catch (err) {
console.error('Error:', err.message);
}
}
await conn.commit();
await conn.close();
}
```
---
### 方案B: Node.js + disql命令行最稳定
**优势**: 使用官方工具,最可靠
**实现步骤**:
1. 检测disql.exe路径
2. 使用child_process调用disql
3. 解析输出获取结果
**架构**:
```
Node.js (smart-executor-disql.js)
调用 disql.exe
执行 SQL文件
解析输出
```
**代码示例**:
```javascript
const { spawn } = require('child_process');
function executeWithDisql(host, port, user, password, sqlFile) {
return new Promise((resolve, reject) => {
const disql = spawn('disql', [
`${user}/${password}@${host}:${port}`,
'@' + sqlFile
]);
let output = '';
disql.stdout.on('data', data => output += data);
disql.on('close', code => {
if (code === 0) resolve(output);
else reject(new Error(output));
});
});
}
```
---
### 方案C: Node.js + Java JDBC桥接最完整
**优势**: 功能最强大,错误处理最好
**实现步骤**:
1. 创建Java执行器类
2. Node.js通过child_process调用
3. JSON格式传递结果
**架构**:
```
Node.js (auto-executor.js)
生成并编译 SQLExecutor.java
调用 java -cp DmJdbcDriver8.jar SQLExecutor
返回JSON格式结果
```
---
## 三、实施建议
### 🎯 推荐实施顺序
#### 第一步: 尝试dmdb驱动最优
```bash
cd d:/pg2dm-converter
npm install dmdb
```
如果安装成功 → 使用方案A
如果安装失败 → 进入第二步
#### 第二步: 使用disql备选
```bash
# 检查disql是否可用
D:\sortware\dm_manager\bin\disql.exe -h
```
如果可用 → 使用方案B
如果不可用 → 进入第三步
#### 第三步: Java JDBC保底
已经实现在auto-executor.js中
---
## 四、具体实现计划
### 立即可行方案: 改进现有的Java JDBC方案
**当前问题**: 编译和类路径问题
**解决方案**:
1. 预编译Java类
2. 使用绝对路径
3. 改进错误处理
**修复后的架构**:
```javascript
// 1. 一次性编译Java执行器
function compileJavaExecutor() {
const javacExe = 'D:\\sortware\\dm_manager\\jdk\\bin\\javac.exe';
const jdbcJar = 'D:\\sortware\\dm_manager\\drivers\\jdbc\\DmJdbcDriver8.jar';
const javaFile = path.join(__dirname, 'DMSQLExecutor.java');
execSync(`"${javacExe}" -encoding UTF-8 -cp "${jdbcJar}" "${javaFile}"`);
}
// 2. 执行SQL
function executeSQL(sqlFile, host, port, user, password) {
const javaExe = 'D:\\sortware\\dm_manager\\jdk\\bin\\java.exe';
const jdbcJar = 'D:\\sortware\\dm_manager\\drivers\\jdbc\\DmJdbcDriver8.jar';
const classPath = `${jdbcJar};${__dirname}`;
return spawn(javaExe, [
'-cp', classPath,
'DMSQLExecutor',
host, port, user, password, sqlFile
]);
}
```
---
## 五、最终推荐
### 🏆 最佳方案组合
**方案**: dmdb + disql
**理由**:
1. **dmdb**: 原生Node.js最佳集成体验
2. **disql**: 官方工具,作为备选方案
3. 两者都不依赖Java编译
**实施步骤**:
```bash
# 1. 安装dmdb
npm install dmdb
# 2. 创建unified-executor.js统一执行器
# - 优先使用dmdb
# - 如果dmdb不可用回退到disql
# - 两者都不可用,提示用户手动执行
# 3. 测试
node unified-executor.js output/*_dm.sql
```
---
## 六、代码实现对比
### dmdb方式推荐
```javascript
// 简洁、原生、Promise
const conn = await dmdb.createConnection(connectString);
await conn.execute(sql);
await conn.commit();
```
### disql方式稳定
```bash
# 直接调用官方工具
disql SYSDBA/@1sdgCq456@219.142.42.183:5256 @output/schema_dm.sql
```
### JDBC方式复杂
```javascript
// 需要Java代码 + 编译 + 调用
const java = spawn('java', ['-cp', classpath, 'Executor', ...args]);
```
---
## 七、安装dmdb可能遇到的问题
### 问题1: 需要C++编译环境
**解决**: 安装Windows Build Tools
```bash
npm install --global windows-build-tools
```
### 问题2: Python依赖
**解决**: 安装Python 2.7或3.x
### 问题3: 网络问题
**解决**: 使用淘宝镜像
```bash
npm install dmdb --registry=https://registry.npmmirror.com
```
### 问题4: 完全离线环境
**解决**: 使用disql方案
---
## 八、性能对比
| 方案 | 启动速度 | 执行速度 | 错误处理 | 易用性 |
|------|---------|---------|---------|--------|
| dmdb | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| disql | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| JDBC | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
---
## 九、总结
**最优方案**:
1. **首选**: npm install dmdb → 完美集成
2. **备选**: 使用disql命令行 → 最稳定
3. **保底**: Java JDBC已实现→ 功能最强
**立即行动**:
```bash
# 尝试安装dmdb
cd d:/pg2dm-converter
npm install dmdb
# 如果成功,我立即创建 dmdb-executor.js
# 如果失败,我创建 disql-executor.js
```
**预期效果**:
- 一键自动执行所有SQL
- 详细的成功/失败统计
- 支持断点续传
- 可重复执行
---
## 附录:参考资料
- [达梦官方文档 - JDBC接口](https://eco.dameng.com/document/dm/zh-cn/app-dev/java-jdbc.html)
- [达梦官方文档 - Node.js编程](https://eco.dameng.com/document/dm/zh-cn/pm/nodejs-rogramming-guide.html)
- [达梦官方文档 - disql工具](https://eco.dameng.com/document/dm/zh-cn/pm/getting-started-disql.html)
- [GitHub - GORM DaMeng驱动](https://github.com/godoes/gorm-dameng)