테이블 간 조인 관계 조회 기능 추가
- 두 테이블 간의 조인 관계를 조회하는 API를 추가하였습니다. 이 API는 메인 테이블과 디테일 테이블을 파라미터로 받아, 해당 테이블 간의 조인 관계를 반환합니다. - DataflowService에 조인 관계 조회 메서드를 구현하여, 회사 코드에 따라 적절한 조인 정보를 필터링합니다. - 프론트엔드에서 조인 관계를 캐시하여, 반복적인 API 호출을 줄이고 성능을 개선하였습니다. 이로 인해 마스터-디테일 저장 기능의 효율성이 향상되었습니다.
This commit is contained in:
@@ -759,3 +759,45 @@ export async function getAllRelationships(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 두 테이블 간의 조인 관계 조회 (마스터-디테일 저장용)
|
||||
*/
|
||||
export async function getJoinRelationship(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { mainTable, detailTable } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
if (!mainTable || !detailTable) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "메인 테이블과 디테일 테이블이 필요합니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// DataflowService에서 조인 관계 조회
|
||||
const { DataflowService } = await import("../services/dataflowService");
|
||||
const dataflowService = new DataflowService();
|
||||
|
||||
const result = await dataflowService.getJoinRelationshipBetweenTables(
|
||||
mainTable,
|
||||
detailTable,
|
||||
companyCode
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("조인 관계 조회 실패:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "조인 관계 조회 실패",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
executeOptimizedButton,
|
||||
executeSimpleDataflow,
|
||||
getJobStatus,
|
||||
getJoinRelationship,
|
||||
} from "../controllers/buttonDataflowController";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
|
||||
@@ -61,6 +62,13 @@ router.post("/execute-simple", executeSimpleDataflow);
|
||||
// 백그라운드 작업 상태 조회
|
||||
router.get("/job-status/:jobId", getJobStatus);
|
||||
|
||||
// ============================================================================
|
||||
// 🔥 테이블 관계 조회 (마스터-디테일 저장용)
|
||||
// ============================================================================
|
||||
|
||||
// 두 테이블 간의 조인 관계 조회
|
||||
router.get("/join-relationship/:mainTable/:detailTable", getJoinRelationship);
|
||||
|
||||
// ============================================================================
|
||||
// 🔥 레거시 호환성 (기존 API와 호환)
|
||||
// ============================================================================
|
||||
|
||||
@@ -337,6 +337,110 @@ export class DataflowService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 두 테이블 간의 조인 관계 조회 (마스터-디테일 저장용)
|
||||
* @param mainTable 메인 테이블명 (마스터)
|
||||
* @param detailTable 디테일 테이블명 (리피터)
|
||||
* @param companyCode 회사코드
|
||||
* @returns 조인 컬럼 매핑 정보
|
||||
*/
|
||||
async getJoinRelationshipBetweenTables(
|
||||
mainTable: string,
|
||||
detailTable: string,
|
||||
companyCode: string
|
||||
): Promise<{
|
||||
found: boolean;
|
||||
mainColumn?: string;
|
||||
detailColumn?: string;
|
||||
relationshipType?: string;
|
||||
}> {
|
||||
try {
|
||||
logger.info(
|
||||
`DataflowService: 테이블 간 조인 관계 조회 - 메인: ${mainTable}, 디테일: ${detailTable}`
|
||||
);
|
||||
|
||||
// 양방향 조회 (from → to 또는 to → from)
|
||||
let queryText = `
|
||||
SELECT
|
||||
from_table_name,
|
||||
from_column_name,
|
||||
to_table_name,
|
||||
to_column_name,
|
||||
relationship_type,
|
||||
settings
|
||||
FROM table_relationships
|
||||
WHERE is_active = 'Y'
|
||||
AND (
|
||||
(from_table_name = $1 AND to_table_name = $2)
|
||||
OR (from_table_name = $2 AND to_table_name = $1)
|
||||
)
|
||||
`;
|
||||
const params: any[] = [mainTable, detailTable];
|
||||
|
||||
// 관리자가 아닌 경우 회사코드 제한
|
||||
if (companyCode !== "*") {
|
||||
queryText += ` AND (company_code = $3 OR company_code = '*')`;
|
||||
params.push(companyCode);
|
||||
}
|
||||
|
||||
queryText += ` LIMIT 1`;
|
||||
|
||||
const result = await queryOne<{
|
||||
from_table_name: string;
|
||||
from_column_name: string;
|
||||
to_table_name: string;
|
||||
to_column_name: string;
|
||||
relationship_type: string;
|
||||
settings: any;
|
||||
}>(queryText, params);
|
||||
|
||||
if (!result) {
|
||||
logger.info(
|
||||
`DataflowService: 테이블 간 조인 관계 없음 - ${mainTable} ↔ ${detailTable}`
|
||||
);
|
||||
return { found: false };
|
||||
}
|
||||
|
||||
// 방향에 따라 컬럼 매핑 결정
|
||||
// mainTable이 from_table이면 그대로, 아니면 반대로
|
||||
let mainColumn: string;
|
||||
let detailColumn: string;
|
||||
|
||||
if (result.from_table_name === mainTable) {
|
||||
// from → to 방향: mainTable.from_column → detailTable.to_column
|
||||
mainColumn = result.from_column_name;
|
||||
detailColumn = result.to_column_name;
|
||||
} else {
|
||||
// to → from 방향: mainTable.to_column → detailTable.from_column
|
||||
mainColumn = result.to_column_name;
|
||||
detailColumn = result.from_column_name;
|
||||
}
|
||||
|
||||
// 쉼표로 구분된 다중 컬럼인 경우 첫 번째 컬럼만 사용
|
||||
// (추후 다중 컬럼 지원 필요시 확장)
|
||||
if (mainColumn.includes(",")) {
|
||||
mainColumn = mainColumn.split(",")[0].trim();
|
||||
}
|
||||
if (detailColumn.includes(",")) {
|
||||
detailColumn = detailColumn.split(",")[0].trim();
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`DataflowService: 조인 관계 발견 - ${mainTable}.${mainColumn} → ${detailTable}.${detailColumn}`
|
||||
);
|
||||
|
||||
return {
|
||||
found: true,
|
||||
mainColumn,
|
||||
detailColumn,
|
||||
relationshipType: result.relationship_type,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("DataflowService: 테이블 간 조인 관계 조회 실패", error);
|
||||
return { found: false };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 연결 타입별 관계 조회
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user