Commit dc27202b authored by xiegelin's avatar xiegelin

feat: 兼容 Oracle 11g,数据库连接信息迁移到 .env

- 新增 oracle.js(oracledb Thick 模式,11g 必须),查询 USER_TAB_COLUMNS / USER_COL_COMMENTS / USER_TAB_COMMENTS
- 新增 npm run oracle 脚本,依赖 oracledb ^6.4.0
- README 增加 Oracle 前置条件与 macOS Apple 芯片 dmg 安装步骤(绕开 Gatekeeper、清 quarantine)
- mysql.js / postgreSQL.js / oracle.js 全部改为从 .env 读取连接信息,依赖 dotenv ^16.4.5
- 新增 .env.example 模板,.env 已加入 .gitignore
Co-Authored-By: default avatarClaude Opus 4.7 (1M context) <noreply@anthropic.com>
parent 0bddf01a
# 复制本文件为 .env 并按实际填写。.env 已被 .gitignore,不会提交。
# ============ MySQL ============
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=your_database
# ============ PostgreSQL ============
PGSQL_HOST=localhost
PGSQL_PORT=5432
PGSQL_USER=postgres
PGSQL_PASSWORD=your_password
PGSQL_DATABASE=your_database
# ============ Oracle(11g 必须 Thick 模式 + Instant Client,详见 README)============
ORACLE_USER=your_user
ORACLE_PASSWORD=your_password
# connectString 两种写法:
# 1) Easy Connect(推荐,service_name):host:port/service_name
# 2) TNS 描述符(11g 用 SID 必须这个写法):
# (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.10.10.139)(PORT=1521))(CONNECT_DATA=(SID=orcl)))
ORACLE_CONNECT_STRING=host:port/service_name
# 可选:Instant Client 路径。已配 PATH/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH 的话留空即可
# ORACLE_CLIENT_LIB_DIR=/path/to/instantclient_19_8
yarn.lock
node_modules
*.xml
\ No newline at end of file
*.xml
.env
......@@ -4,26 +4,28 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Node.js CLI utility that generates Draw.io (diagrams.net) XML files from database table schemas or Markdown tables. Supports MySQL, PostgreSQL, and Markdown-to-Draw.io conversion. Queries `information_schema` to extract column metadata, then outputs mxGraph XML importable into Draw.io.
Node.js CLI utility that generates Draw.io (diagrams.net) XML files from database table schemas or Markdown tables. Supports MySQL, PostgreSQL, Oracle (11g+), and Markdown-to-Draw.io conversion. Queries the database catalog to extract column metadata, then outputs mxGraph XML importable into Draw.io.
## Commands
```bash
npm install # Install dependencies (mysql2, pg)
npm install # Install dependencies (mysql2, pg, oracledb)
npm run dev # Run MySQL version (interactive CLI)
npm run mysql # Same as dev
npm run pgsql # Run PostgreSQL version (interactive CLI)
npm run oracle # Run Oracle version (interactive CLI), Oracle 11g verified
npm run md2drawio # Convert Markdown table file to Draw.io XML
```
Requires Node.js v18+. No test suite or linter is configured.
Requires Node.js v18+. Oracle 11g additionally requires Oracle Instant Client (oracledb Thick mode) — see README and `oracle.js` header for setup. No test suite or linter is configured.
## Architecture
Three independent entry points, no shared modules:
Four independent entry points, no shared modules:
- `mysql.js` — MySQL via `mysql2/promise`, queries `information_schema.COLUMNS` and `information_schema.TABLES`. Generates both table-structure XML (with table comment in label) and sample-data XML.
- `postgreSQL.js` — PostgreSQL via `pg`, joins `information_schema.columns` with `pg_catalog.pg_description` for column comments. Generates table-structure XML only (no table comment in label, no sample-data XML).
- `postgreSQL.js` — PostgreSQL via `pg`, joins `information_schema.columns` with `pg_catalog.pg_description` for column comments. Generates table-structure XML only (table comment included in label, no sample-data XML).
- `oracle.js` — Oracle via `oracledb` in Thick mode (required for 11g; Thin mode only supports 12.1+). Queries `USER_TAB_COLUMNS` / `USER_COL_COMMENTS` / `USER_TAB_COMMENTS` (current schema only). Generates table-structure XML only (table comment included in label, no sample-data XML). For 11g SID-style connections, `connectString` must use a TNS descriptor (Easy Connect does not accept `host:port:SID`).
- `mdToDrawio.js` — Parses a Markdown table file (pipe-delimited) and generates a Draw.io table XML into `sampleDataXml/`.
### Core Flow (mysql.js / postgreSQL.js)
......@@ -32,22 +34,26 @@ Three independent entry points, no shared modules:
3. **Database Query**: fetches column names + comments from information_schema
4. **XML Generation**: `generateXMLWithTableColumns` builds mxGraph XML with swimlane container and per-column cells. Audit fields (created_at, updated_at, deleted_at, etc.) are styled gray (#B3B3B3). MySQL version also calls `generateSampleDataXML` for a horizontal table layout.
### Key Cross-File Difference
MySQL result rows use uppercase keys (`row.COLUMN_NAME`, `row.COLUMN_COMMENT`) while PostgreSQL uses lowercase (`row.column_name`, `row.column_comment`). This matters when adding shared logic or modifying XML generation.
### Key Cross-File Differences
- MySQL result rows use uppercase keys (`row.COLUMN_NAME`, `row.COLUMN_COMMENT`); PostgreSQL uses lowercase (`row.column_name`, `row.column_comment`); Oracle uses uppercase (`row.COLUMN_NAME`, `row.COLUMN_COMMENT`) because `oracledb` returns identifiers as Oracle stores them.
- Oracle table-name input is normalized to UPPER_SNAKE_CASE (Oracle's storage default) instead of lower snake_case. The audit-field gray-out list in `oracle.js` uses uppercase column names accordingly.
### Output Directories
- `tableStructureXml/` — swimlane-style table structure diagrams
- `sampleDataXml/` — horizontal table-layout diagrams for sample data
### Database Configuration
Credentials are hardcoded at the top of each database file. Modify directly in source to point at different databases.
Credentials live in `.env` (gitignored) at the project root. `mysql.js`, `postgreSQL.js`, and `oracle.js` all call `require('dotenv').config()` and read from `process.env`. Variable groups: `MYSQL_*`, `PGSQL_*`, `ORACLE_*` (plus optional `ORACLE_CLIENT_LIB_DIR` for Instant Client path). See `.env.example` for the canonical list. Each script fails fast with a "请创建 .env" message when its required vars are missing.
### Known Constraints
- `&` in column comments breaks XML output (no escaping)
- Table names must not contain Chinese characters
- Fixed geometry: x=340, y=140, width=260 for structure XML; colWidth=120 for sample data XML
- PostgreSQL version hardcodes schema to `public`
- PostgreSQL version does not generate sample-data XML or include table comments in the label
- PostgreSQL version does not generate sample-data XML
- Oracle version uses `USER_*` views (current login user only); switch to `ALL_*` + `OWNER` filter for cross-schema use
- Oracle 11g requires Thick mode + Instant Client; without it, `oracledb.initOracleClient()` throws `DPI-1047`
- Oracle SID connections must use a TNS descriptor in `connectString`; only service_name works with Easy Connect
## Language
README and console messages are in Chinese. Code uses English variable/function names.
......@@ -2,6 +2,7 @@
node v18
```bash
npm install
cp .env.example .env # 然后按需修改 .env 里的连接信息
```
### 可用命令
......@@ -11,15 +12,69 @@ npm install
| `npm run dev` | 运行 MySQL 版本,交互式输入表名,生成表结构 XML 和示例数据 XML |
| `npm run mysql` | 同 `npm run dev` |
| `npm run pgsql` | 运行 PostgreSQL 版本,交互式输入表名,生成表结构 XML |
| `npm run oracle` | 运行 Oracle 版本(已验证 11g),交互式输入表名,生成表结构 XML |
| `npm run md2drawio` | 将 Markdown 表格文件转换为 Draw.io XML |
### 使用方法:
1. 配置数据源:MySQL 见 `mysql.js` 顶部,PostgreSQL 见 `postgreSQL.js` 顶部
1. 配置数据源:复制 `.env.example``.env`,填入 MySQL / PostgreSQL / Oracle 的连接信息(只填用得到的那段即可)
2. 运行对应命令后,输入目标表名,支持多个,按英文逗号或中文逗号拼接
3. 运行成功后,表结构 XML 输出在 `tableStructureXml/` 目录下,示例数据 XML 输出在 `sampleDataXml/` 目录下
4. 打开 XML 文件将内容粘贴到 Draw.io 编辑器中
5. `npm run md2drawio` 需输入 Markdown 文件路径,输出在 `sampleDataXml/` 目录下
### Oracle 版本前置条件(重要)
Oracle 11g 必须使用 `oracledb`**Thick 模式**(Thin 模式仅支持 12.1+),运行机器需要先装好 Oracle Instant Client。下面分平台说明。
> 启动若报 `DPI-1047: Cannot locate a 64-bit Oracle Client library`,即是 Instant Client 没装好或路径没配上。
#### 通用:下载 Instant Client(Basic 包即可,约 50MB)
| 平台 | 下载页 |
| --- | --- |
| macOS (Apple 芯片,M1/M2/M3/M4/M5 等) | https://www.oracle.com/database/technologies/instant-client/macos-arm64-downloads.html |
| macOS (Intel) | https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html |
| Linux x86_64 | https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html |
| Windows x64 | https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html |
#### macOS(Apple 芯片)安装步骤
下载下来的是 `.dmg`**不要双击运行 dmg 里自带的 `install_ic.sh`**,那个脚本会被 macOS Gatekeeper 拦截(弹窗"Apple 无法验证…包含可能危害 Mac 安全或泄漏隐私的恶意软件")。直接挂载镜像、手动复制即可:
```bash
# 1) 挂载 dmg(路径换成你下载的实际版本号)
hdiutil attach ~/Downloads/instantclient-basic-macos.arm64-23.26.1.0.0.dmg
# 2) 把库文件复制到 /opt/oracle/instantclient_23_26(目录名自取,建议带版本号)
sudo mkdir -p /opt/oracle/instantclient_23_26
sudo cp -R /Volumes/instantclient-basic-macos.arm64-23.26.1.0.0/* /opt/oracle/instantclient_23_26/
# 3) 清掉 macOS 隔离标记(必做!不清的话 dylib 会被系统拒绝加载)
sudo xattr -dr com.apple.quarantine /opt/oracle/instantclient_23_26
# 4) 验证:能列出 libclntsh.dylib 即成功
ls /opt/oracle/instantclient_23_26/libclntsh.dylib
# 5) 卸载 dmg
hdiutil detach /Volumes/instantclient-basic-macos.arm64-23.26.1.0.0
```
然后在项目根目录的 `.env` 里设置:
```
ORACLE_CLIENT_LIB_DIR=/opt/oracle/instantclient_23_26
```
#### macOS(Intel)/ Linux / Windows 安装步骤
下载的是 zip 包,解压到任意目录后任选一种方式让 `oracledb` 找到它:
- **方式 A(推荐,零侵入)**:在 `.env` 里设 `ORACLE_CLIENT_LIB_DIR=<解压路径>`
- **方式 B(系统级生效)**
- macOS Intel:`export DYLD_LIBRARY_PATH=<解压路径>:$DYLD_LIBRARY_PATH`
- Linux:`export LD_LIBRARY_PATH=<解压路径>:$LD_LIBRARY_PATH`
- Windows:把解压目录加入系统 `PATH`
### 注意事项:
1. 生成的 XML 文件中,不能有 `&` 符号。常见问题是这个符号会出现在字段注释中。
2. 表名不能包含中文字符。
\ No newline at end of file
2. 表名不能包含中文字符。
3. Oracle 标识符默认全大写存储,输入 camelCase 会自动转成 `UPPER_SNAKE_CASE`
\ No newline at end of file
require('dotenv').config();
const mysql = require('mysql2/promise');
const readline = require('readline');
const fs = require('fs');
......@@ -16,18 +17,19 @@ function askQuestion(query) {
async function main() {
try {
// Get database connection details from user
const host = 'localhost';
const port = '3306';
const user = 'root';
const password = '12345678';
const database = 'hospital';
// const host = '10.10.10.132';
// const port = '3306';
// const user = 'root';
// const password = 'fxkc@2024';
// const database = 'data_governance_mining';
// 从 .env 读取连接信息(缺失时给出明确提示,参考 .env.example)
const host = process.env.MYSQL_HOST;
const port = process.env.MYSQL_PORT;
const user = process.env.MYSQL_USER;
const password = process.env.MYSQL_PASSWORD;
const database = process.env.MYSQL_DATABASE;
if (!host || !port || !user || password === undefined || !database) {
console.error(
'缺少 MySQL 连接配置,请在项目根目录创建 .env 文件(可参考 .env.example)'
);
return;
}
const mode = await askQuestion(
'请选择模式 — 1: 所有表, 2: 指定表 (默认2): '
......
/**
* Oracle 数据库表结构 → Draw.io XML(先支持 Oracle 11g)
*
* ===========================================================================
* 前置条件(重要!第一次运行务必先看完)
* ---------------------------------------------------------------------------
* Oracle 11g 必须使用 oracledb 的 Thick 模式,因此运行机器需要安装
* Oracle Instant Client(oracledb 的 Thin 模式仅支持 Oracle 12.1+)。
*
* 1) 下载 Instant Client(推荐 19c,对 11g 向下兼容)
* macOS (Intel) https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html
* macOS (Apple 芯片) Oracle 未提供原生 ARM 版本,需用 Rosetta 2 跑 Node.js,或选用更老版本
* Linux x86_64 https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html
* Windows x64 https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html
*
* 2) 解压后任选一种方式让程序找到它
* a. 配系统环境变量(推荐,一劳永逸)
* macOS: export DYLD_LIBRARY_PATH=/path/to/instantclient_19_8
* Linux: export LD_LIBRARY_PATH=/path/to/instantclient_19_8
* Windows: 把目录加入系统 PATH
* b. 在代码里显式指定路径:
* 把下方 initOracleClient 调用改成
* oracledb.initOracleClient({ libDir: '/path/to/instantclient_19_8' });
*
* 3) 安装依赖
* npm install
*
* 如果启动时报 "DPI-1047: Cannot locate a 64-bit Oracle Client library"
* 就是 Instant Client 没装好或路径没识别到,按上面 1、2 步重新检查。
* ===========================================================================
*/
require('dotenv').config();
const oracledb = require('oracledb');
const readline = require('readline');
const fs = require('fs');
try {
// 启用 Thick 模式(Oracle 11g 必须)
// 优先用 .env 里的 ORACLE_CLIENT_LIB_DIR;否则依赖系统 PATH/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH
const libDir = process.env.ORACLE_CLIENT_LIB_DIR;
oracledb.initOracleClient(libDir ? { libDir } : undefined);
} catch (err) {
console.error('Oracle Instant Client 初始化失败:', err.message);
console.error('请确认已安装 Oracle Instant Client 并配置好库路径,详见文件顶部说明。');
process.exit(1);
}
// 让查询结果以对象形式返回(默认是数组)
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
function askQuestion(query) {
return new Promise((resolve) => {
rl.question(query, resolve);
});
}
async function main() {
let connection;
try {
// 从 .env 读取连接信息(缺失时给出明确提示,参考 .env.example)
const user = process.env.ORACLE_USER;
const password = process.env.ORACLE_PASSWORD;
const connectString = process.env.ORACLE_CONNECT_STRING;
if (!user || password === undefined || !connectString) {
console.error(
'缺少 Oracle 连接配置,请在项目根目录创建 .env 文件(可参考 .env.example)'
);
return;
}
const mode = await askQuestion(
'请选择模式 — 1: 所有表, 2: 指定表 (默认2): '
);
console.log('\nConnecting to database...');
connection = await oracledb.getConnection({ user, password, connectString });
console.log('Connected to database successfully!\n');
let tableNames;
if (mode.trim() === '1') {
// 当前用户下的所有表(如需跨 schema 改用 ALL_TABLES + OWNER 过滤)
const allTablesResult = await connection.execute(
`SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME`
);
tableNames = allTablesResult.rows.map((r) => r.TABLE_NAME);
console.log(`共找到 ${tableNames.length} 张表\n`);
} else {
const input = await askQuestion(
'Enter table names (separated by commas): '
);
if (!input) {
console.log('表名不得为空!');
return;
}
tableNames = input
.split(/[,,]/)
.map((name) => name.trim())
.filter((name) => name)
.map((name) => {
if (/[一-龥]/.test(name)) {
console.error(`Table name "${name}" 不能有中文,已跳过.`);
return null;
}
// Oracle 标识符默认全大写:camelCase → UPPER_SNAKE_CASE
// 仅在「小写→大写」边界插入下划线,避免破坏已是 UPPER_SNAKE 的输入
return name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
})
.filter(Boolean);
}
// 列名 + 列注释
const columnSql = `
SELECT
c.COLUMN_NAME,
cc.COMMENTS AS COLUMN_COMMENT
FROM USER_TAB_COLUMNS c
LEFT JOIN USER_COL_COMMENTS cc
ON c.TABLE_NAME = cc.TABLE_NAME
AND c.COLUMN_NAME = cc.COLUMN_NAME
WHERE c.TABLE_NAME = :tableName
ORDER BY c.COLUMN_ID
`;
// 表注释
const tableCommentSql = `
SELECT COMMENTS FROM USER_TAB_COMMENTS WHERE TABLE_NAME = :tableName
`;
for (const processedTableName of tableNames) {
console.log('Processing table:', processedTableName);
const result = await connection.execute(columnSql, {
tableName: processedTableName,
});
const rows = result.rows;
const tableCommentResult = await connection.execute(tableCommentSql, {
tableName: processedTableName,
});
const tableComment = tableCommentResult.rows[0]?.COMMENTS || '';
if (rows.length === 0) {
console.error(
`***** No results found for table ${processedTableName}. *****`
);
} else {
generateXMLWithTableColumns(processedTableName, rows, tableComment);
console.log(
`===== XML file generated successfully for ${processedTableName}! =====`
);
}
}
} catch (error) {
console.error('Error:', error.message);
} finally {
if (connection) {
try {
await connection.close();
console.log('\nConnection closed.');
} catch (closeErr) {
console.error('Connection close error:', closeErr.message);
}
}
rl.close();
}
}
function generateXMLWithTableColumns(tableName, rows, tableComment) {
const label = tableComment ? `${tableName} &#10;${tableComment}` : tableName;
let xmlContent = `<mxGraphModel>
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<object label="${label}" id="2">
<mxCell style="swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=40;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="340" y="140" width="260" height="${
30 + rows.length * 30
}" as="geometry"/>
</mxCell>
</object>`;
rows.forEach((row, index) => {
const cellValue = `${row.COLUMN_NAME} ${row.COLUMN_COMMENT || ''}`;
const cellId = index + 3;
// Oracle 列名默认全大写
const unimportantColumns = [
'CREATED_AT',
'CREATE_TIME',
'CREATED_CODE',
'CREATE_CODE',
'UPDATED_AT',
'UPDATE_TIME',
'UPDATED_CODE',
'UPDATE_CODE',
'DELETED_AT',
'DELETED_CODE',
'DELETE_FLAG',
].includes(row.COLUMN_NAME);
const style = unimportantColumns
? 'text;strokeColor=default;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;fontColor=#B3B3B3;'
: 'text;strokeColor=default;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;';
xmlContent += `
<mxCell id="${cellId}" value="${cellValue}" style="${style}" vertex="1" parent="2">
<mxGeometry y="${
30 + index * 30
}" width="260" height="30" as="geometry"/>
</mxCell>`;
});
xmlContent += `
</root>
</mxGraphModel>`;
const filePath = `tableStructureXml/${tableName}.xml`;
if (fs.existsSync(filePath)) {
console.log(`[覆盖] ${filePath} 已存在,已覆盖。`);
}
fs.writeFileSync(filePath, xmlContent);
}
main();
{
"name": "drawio-utils",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "drawio-utils",
"version": "1.0.0",
"dependencies": {
"dotenv": "^16.4.5",
"mysql2": "^3.6.0",
"oracledb": "^6.4.0",
"pg": "^8.11.3"
}
},
"node_modules/aws-ssl-profiles": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
}
},
"node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"license": "MIT",
"dependencies": {
"is-property": "^1.0.2"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
"license": "MIT"
},
"node_modules/long": {
"version": "5.3.1",
"resolved": "https://registry.npmmirror.com/long/-/long-5.3.1.tgz",
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
"license": "Apache-2.0"
},
"node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/lru.min": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/lru.min/-/lru.min-1.1.2.tgz",
"integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=1.30.0",
"node": ">=8.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wellwelwel"
}
},
"node_modules/mysql2": {
"version": "3.14.0",
"resolved": "https://registry.npmmirror.com/mysql2/-/mysql2-3.14.0.tgz",
"integrity": "sha512-8eMhmG6gt/hRkU1G+8KlGOdQi2w+CgtNoD1ksXZq9gQfkfDsX4LHaBwTe1SY0Imx//t2iZA03DFnyYKPinxSRw==",
"license": "MIT",
"dependencies": {
"aws-ssl-profiles": "^1.1.1",
"denque": "^2.1.0",
"generate-function": "^2.3.1",
"iconv-lite": "^0.6.3",
"long": "^5.2.1",
"lru.min": "^1.0.0",
"named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5",
"sqlstring": "^2.3.2"
},
"engines": {
"node": ">= 8.0"
}
},
"node_modules/named-placeholders": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/named-placeholders/-/named-placeholders-1.1.3.tgz",
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
"license": "MIT",
"dependencies": {
"lru-cache": "^7.14.1"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/oracledb": {
"version": "6.10.0",
"resolved": "https://registry.npmmirror.com/oracledb/-/oracledb-6.10.0.tgz",
"integrity": "sha512-kGUumXmrEWbSpBuKJyb9Ip3rXcNgKK6grunI3/cLPzrRvboZ6ZoLi9JQ+z6M/RIG924tY8BLflihL4CKKQAYMA==",
"hasInstallScript": true,
"license": "(Apache-2.0 OR UPL-1.0)",
"engines": {
"node": ">=14.17"
}
},
"node_modules/pg": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.17.1.tgz",
"integrity": "sha512-EIR+jXdYNSMOrpRp7g6WgQr7SaZNZfS7IzZIO0oTNEeibq956JxeD15t3Jk3zZH0KH8DmOIx38qJfQenoE8bXQ==",
"license": "MIT",
"dependencies": {
"pg-connection-string": "^2.10.0",
"pg-pool": "^3.11.0",
"pg-protocol": "^1.11.0",
"pg-types": "2.2.0",
"pgpass": "1.0.5"
},
"engines": {
"node": ">= 16.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.3.0"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
"integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
"license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.0.tgz",
"integrity": "sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg==",
"license": "MIT"
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"license": "ISC",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz",
"integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==",
"license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz",
"integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==",
"license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
"integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/seq-queue": {
"version": "0.0.5",
"resolved": "https://registry.npmmirror.com/seq-queue/-/seq-queue-0.0.5.tgz",
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmmirror.com/sqlstring/-/sqlstring-2.3.3.tgz",
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
}
}
}
......@@ -7,10 +7,13 @@
"dev": "node mysql.js",
"mysql": "node mysql.js",
"pgsql": "node postgreSQL.js",
"oracle": "node oracle.js",
"md2drawio": "node mdToDrawio.js"
},
"dependencies": {
"dotenv": "^16.4.5",
"mysql2": "^3.6.0",
"oracledb": "^6.4.0",
"pg": "^8.11.3"
}
}
\ No newline at end of file
require('dotenv').config();
const { Client } = require('pg');
const readline = require('readline');
const fs = require('fs');
......@@ -16,19 +17,19 @@ function askQuestion(query) {
async function main() {
try {
// PostgreSQL connection configuration
const host = '172.16.1.173';
const port = '5432';
const user = 'postgres';
const password = '123456';
const database = 'diting';
// Alternative configuration (commented out)
// const host = '10.10.10.132';
// const port = '5432';
// const user = 'postgres';
// const password = 'your_password';
// const database = 'your_database';
// 从 .env 读取连接信息(缺失时给出明确提示,参考 .env.example)
const host = process.env.PGSQL_HOST;
const port = process.env.PGSQL_PORT;
const user = process.env.PGSQL_USER;
const password = process.env.PGSQL_PASSWORD;
const database = process.env.PGSQL_DATABASE;
if (!host || !port || !user || password === undefined || !database) {
console.error(
'缺少 PostgreSQL 连接配置,请在项目根目录创建 .env 文件(可参考 .env.example)'
);
return;
}
const mode = await askQuestion(
'请选择模式 — 1: 所有表, 2: 指定表 (默认2): '
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment