외부 db연동 구현

This commit is contained in:
dohyeons
2025-10-01 14:36:46 +09:00
parent 12087cbdd7
commit 2ee4dd0b58
8 changed files with 212 additions and 18 deletions

View File

@@ -18,6 +18,8 @@ import {
GetTemplatesResponse,
CreateTemplateRequest,
} from "../types/report";
import { DatabaseConnectorFactory } from "../database/DatabaseConnectorFactory";
import { ExternalDbConnectionService } from "./externalDbConnectionService";
export class ReportService {
/**
@@ -165,6 +167,7 @@ export class ReportService {
query_type,
sql_query,
parameters,
external_connection_id,
display_order,
created_at,
created_by,
@@ -449,9 +452,10 @@ export class ReportService {
query_type,
sql_query,
parameters,
external_connection_id,
display_order,
created_by
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`;
for (const originalQuery of queriesResult.rows) {
@@ -463,6 +467,7 @@ export class ReportService {
originalQuery.query_type,
originalQuery.sql_query,
JSON.stringify(originalQuery.parameters),
originalQuery.external_connection_id || null,
originalQuery.display_order,
userId,
]);
@@ -595,9 +600,10 @@ export class ReportService {
query_type,
sql_query,
parameters,
external_connection_id,
display_order,
created_by
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`;
for (let i = 0; i < data.queries.length; i++) {
@@ -609,6 +615,7 @@ export class ReportService {
q.type,
q.sqlQuery,
JSON.stringify(q.parameters),
(q as any).externalConnectionId || null, // 외부 DB 연결 ID
i,
userId,
]);
@@ -620,26 +627,34 @@ export class ReportService {
}
/**
* 쿼리 실행
* 쿼리 실행 (내부 DB 또는 외부 DB)
*/
async executeQuery(
reportId: string,
queryId: string,
parameters: Record<string, any>,
sqlQuery?: string
sqlQuery?: string,
externalConnectionId?: number | null
): Promise<{ fields: string[]; rows: any[] }> {
let sql_query: string;
let queryParameters: string[] = [];
let connectionId: number | null = externalConnectionId ?? null;
// 테스트 모드 (sqlQuery 직접 전달)
if (sqlQuery) {
sql_query = sqlQuery;
// 파라미터 순서 추출
// 파라미터 순서 추출 (등장 순서대로)
const matches = sqlQuery.match(/\$\d+/g);
if (matches) {
queryParameters = Array.from(new Set(matches)).sort((a, b) => {
return parseInt(a.substring(1)) - parseInt(b.substring(1));
});
const seen = new Set<string>();
const result: string[] = [];
for (const match of matches) {
if (!seen.has(match)) {
seen.add(match);
result.push(match);
}
}
queryParameters = result;
}
} else {
// DB에서 쿼리 조회
@@ -656,6 +671,7 @@ export class ReportService {
queryParameters = Array.isArray(queryResult.parameters)
? queryResult.parameters
: [];
connectionId = queryResult.external_connection_id;
}
// 파라미터 배열 생성 ($1, $2 순서대로)
@@ -665,8 +681,49 @@ export class ReportService {
}
try {
// 쿼리 실행
const result = await query(sql_query, paramArray);
let result: any[];
// 외부 DB 연결이 있으면 외부 DB에서 실행
if (connectionId) {
// 외부 DB 연결 정보 조회
const connectionResult =
await ExternalDbConnectionService.getConnectionById(connectionId);
if (!connectionResult.success || !connectionResult.data) {
throw new Error("외부 DB 연결 정보를 찾을 수 없습니다.");
}
const connection = connectionResult.data;
// DatabaseConnectorFactory를 사용하여 외부 DB 쿼리 실행
const config = {
host: connection.host,
port: connection.port,
database: connection.database_name,
user: connection.username,
password: connection.password,
connectionTimeout: connection.connection_timeout || 30000,
queryTimeout: connection.query_timeout || 30000,
};
const connector = await DatabaseConnectorFactory.createConnector(
connection.db_type,
config,
connectionId
);
await connector.connect();
try {
const queryResult = await connector.executeQuery(sql_query);
result = queryResult.rows || [];
} finally {
await connector.disconnect();
}
} else {
// 내부 DB에서 실행
result = await query(sql_query, paramArray);
}
// 필드명 추출
const fields = result.length > 0 ? Object.keys(result[0]) : [];