210 lines
6.8 KiB
TypeScript
210 lines
6.8 KiB
TypeScript
/**
|
|
* 디지털 트윈 외부 DB (DO_DY) 연결 및 쿼리 테스트 스크립트
|
|
* READ-ONLY: SELECT 쿼리만 실행
|
|
*/
|
|
|
|
import { Pool } from "pg";
|
|
import mysql from "mysql2/promise";
|
|
import { CredentialEncryption } from "../src/utils/credentialEncryption";
|
|
|
|
async function testDigitalTwinDb() {
|
|
// 내부 DB 연결 (연결 정보 저장용)
|
|
const internalPool = new Pool({
|
|
host: process.env.DB_HOST || "localhost",
|
|
port: parseInt(process.env.DB_PORT || "5432"),
|
|
database: process.env.DB_NAME || "plm",
|
|
user: process.env.DB_USER || "postgres",
|
|
password: process.env.DB_PASSWORD || "ph0909!!",
|
|
});
|
|
|
|
const encryptionKey =
|
|
process.env.ENCRYPTION_SECRET_KEY || "default-secret-key-for-development";
|
|
const encryption = new CredentialEncryption(encryptionKey);
|
|
|
|
try {
|
|
console.log("🚀 디지털 트윈 외부 DB 연결 테스트 시작\n");
|
|
|
|
// 디지털 트윈 외부 DB 연결 정보
|
|
const digitalTwinConnection = {
|
|
name: "디지털트윈_DO_DY",
|
|
description: "디지털 트윈 후판(자재) 재고 정보 데이터베이스 (MariaDB)",
|
|
dbType: "mysql", // MariaDB는 MySQL 프로토콜 사용
|
|
host: "1.240.13.83",
|
|
port: 4307,
|
|
databaseName: "DO_DY",
|
|
username: "root",
|
|
password: "pohangms619!#",
|
|
sslEnabled: false,
|
|
isActive: true,
|
|
};
|
|
|
|
console.log("📝 연결 정보:");
|
|
console.log(` - 이름: ${digitalTwinConnection.name}`);
|
|
console.log(` - DB 타입: ${digitalTwinConnection.dbType}`);
|
|
console.log(` - 호스트: ${digitalTwinConnection.host}:${digitalTwinConnection.port}`);
|
|
console.log(` - 데이터베이스: ${digitalTwinConnection.databaseName}\n`);
|
|
|
|
// 1. 외부 DB 직접 연결 테스트
|
|
console.log("🔍 외부 DB 직접 연결 테스트 중...");
|
|
|
|
const externalConnection = await mysql.createConnection({
|
|
host: digitalTwinConnection.host,
|
|
port: digitalTwinConnection.port,
|
|
database: digitalTwinConnection.databaseName,
|
|
user: digitalTwinConnection.username,
|
|
password: digitalTwinConnection.password,
|
|
connectTimeout: 10000,
|
|
});
|
|
|
|
console.log("✅ 외부 DB 연결 성공!\n");
|
|
|
|
// 2. SELECT 쿼리 실행
|
|
console.log("📊 WSTKKY 테이블 쿼리 실행 중...\n");
|
|
|
|
const query = `
|
|
SELECT
|
|
SKUMKEY -- 제품번호
|
|
, SKUDESC -- 자재명
|
|
, SKUTHIC -- 두께
|
|
, SKUWIDT -- 폭
|
|
, SKULENG -- 길이
|
|
, SKUWEIG -- 중량
|
|
, STOTQTY -- 수량
|
|
, SUOMKEY -- 단위
|
|
FROM DO_DY.WSTKKY
|
|
LIMIT 10
|
|
`;
|
|
|
|
const [rows] = await externalConnection.execute(query);
|
|
|
|
console.log("✅ 쿼리 실행 성공!\n");
|
|
console.log(`📦 조회된 데이터: ${Array.isArray(rows) ? rows.length : 0}건\n`);
|
|
|
|
if (Array.isArray(rows) && rows.length > 0) {
|
|
console.log("🔍 샘플 데이터 (첫 3건):\n");
|
|
rows.slice(0, 3).forEach((row: any, index: number) => {
|
|
console.log(`[${index + 1}]`);
|
|
console.log(` 제품번호(SKUMKEY): ${row.SKUMKEY}`);
|
|
console.log(` 자재명(SKUDESC): ${row.SKUDESC}`);
|
|
console.log(` 두께(SKUTHIC): ${row.SKUTHIC}`);
|
|
console.log(` 폭(SKUWIDT): ${row.SKUWIDT}`);
|
|
console.log(` 길이(SKULENG): ${row.SKULENG}`);
|
|
console.log(` 중량(SKUWEIG): ${row.SKUWEIG}`);
|
|
console.log(` 수량(STOTQTY): ${row.STOTQTY}`);
|
|
console.log(` 단위(SUOMKEY): ${row.SUOMKEY}\n`);
|
|
});
|
|
|
|
// 전체 데이터 JSON 출력
|
|
console.log("📄 전체 데이터 (JSON):");
|
|
console.log(JSON.stringify(rows, null, 2));
|
|
console.log("\n");
|
|
}
|
|
|
|
await externalConnection.end();
|
|
|
|
// 3. 내부 DB에 연결 정보 저장
|
|
console.log("💾 내부 DB에 연결 정보 저장 중...");
|
|
|
|
const encryptedPassword = encryption.encrypt(digitalTwinConnection.password);
|
|
|
|
// 중복 체크
|
|
const existingResult = await internalPool.query(
|
|
"SELECT id FROM flow_external_db_connection WHERE name = $1",
|
|
[digitalTwinConnection.name]
|
|
);
|
|
|
|
let connectionId: number;
|
|
|
|
if (existingResult.rows.length > 0) {
|
|
connectionId = existingResult.rows[0].id;
|
|
console.log(`⚠️ 이미 존재하는 연결 (ID: ${connectionId})`);
|
|
|
|
// 기존 연결 업데이트
|
|
await internalPool.query(
|
|
`UPDATE flow_external_db_connection
|
|
SET description = $1,
|
|
db_type = $2,
|
|
host = $3,
|
|
port = $4,
|
|
database_name = $5,
|
|
username = $6,
|
|
password_encrypted = $7,
|
|
ssl_enabled = $8,
|
|
is_active = $9,
|
|
updated_at = NOW(),
|
|
updated_by = 'system'
|
|
WHERE name = $10`,
|
|
[
|
|
digitalTwinConnection.description,
|
|
digitalTwinConnection.dbType,
|
|
digitalTwinConnection.host,
|
|
digitalTwinConnection.port,
|
|
digitalTwinConnection.databaseName,
|
|
digitalTwinConnection.username,
|
|
encryptedPassword,
|
|
digitalTwinConnection.sslEnabled,
|
|
digitalTwinConnection.isActive,
|
|
digitalTwinConnection.name,
|
|
]
|
|
);
|
|
console.log(`✅ 연결 정보 업데이트 완료`);
|
|
} else {
|
|
// 새 연결 추가
|
|
const result = await internalPool.query(
|
|
`INSERT INTO flow_external_db_connection (
|
|
name,
|
|
description,
|
|
db_type,
|
|
host,
|
|
port,
|
|
database_name,
|
|
username,
|
|
password_encrypted,
|
|
ssl_enabled,
|
|
is_active,
|
|
created_by
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 'system')
|
|
RETURNING id`,
|
|
[
|
|
digitalTwinConnection.name,
|
|
digitalTwinConnection.description,
|
|
digitalTwinConnection.dbType,
|
|
digitalTwinConnection.host,
|
|
digitalTwinConnection.port,
|
|
digitalTwinConnection.databaseName,
|
|
digitalTwinConnection.username,
|
|
encryptedPassword,
|
|
digitalTwinConnection.sslEnabled,
|
|
digitalTwinConnection.isActive,
|
|
]
|
|
);
|
|
connectionId = result.rows[0].id;
|
|
console.log(`✅ 새 연결 추가 완료 (ID: ${connectionId})`);
|
|
}
|
|
|
|
console.log("\n✅ 모든 테스트 완료!");
|
|
console.log(`\n📌 연결 ID: ${connectionId}`);
|
|
console.log(" 이 ID를 사용하여 플로우 관리나 제어 관리에서 외부 DB를 연동할 수 있습니다.");
|
|
|
|
} catch (error: any) {
|
|
console.error("\n❌ 오류 발생:", error.message);
|
|
console.error("상세 정보:", error);
|
|
throw error;
|
|
} finally {
|
|
await internalPool.end();
|
|
}
|
|
}
|
|
|
|
// 스크립트 실행
|
|
testDigitalTwinDb()
|
|
.then(() => {
|
|
console.log("\n🎉 스크립트 완료");
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error("\n💥 스크립트 실패:", error);
|
|
process.exit(1);
|
|
});
|
|
|
|
|