우측 패널 일괄삭제 기능
This commit is contained in:
@@ -200,6 +200,25 @@ export class EntityJoinService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 날짜 컬럼을 YYYY-MM-DD 형식으로 변환하는 SQL 표현식
|
||||
*/
|
||||
private formatDateColumn(
|
||||
tableAlias: string,
|
||||
columnName: string,
|
||||
dataType?: string
|
||||
): string {
|
||||
// date, timestamp 타입이면 TO_CHAR로 변환
|
||||
if (
|
||||
dataType &&
|
||||
(dataType.includes("date") || dataType.includes("timestamp"))
|
||||
) {
|
||||
return `TO_CHAR(${tableAlias}.${columnName}, 'YYYY-MM-DD')`;
|
||||
}
|
||||
// 기본은 TEXT 캐스팅
|
||||
return `${tableAlias}.${columnName}::TEXT`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity 조인이 포함된 SQL 쿼리 생성
|
||||
*/
|
||||
@@ -210,19 +229,30 @@ export class EntityJoinService {
|
||||
whereClause: string = "",
|
||||
orderBy: string = "",
|
||||
limit?: number,
|
||||
offset?: number
|
||||
offset?: number,
|
||||
columnTypes?: Map<string, string> // 컬럼명 → 데이터 타입 매핑
|
||||
): { query: string; aliasMap: Map<string, string> } {
|
||||
try {
|
||||
// 기본 SELECT 컬럼들 (TEXT로 캐스팅하여 record 타입 오류 방지)
|
||||
// "*"는 특별 처리: AS 없이 그냥 main.*만
|
||||
const baseColumns = selectColumns
|
||||
.map((col) => {
|
||||
if (col === "*") {
|
||||
return "main.*";
|
||||
}
|
||||
return `main.${col}::TEXT AS ${col}`;
|
||||
})
|
||||
.join(", ");
|
||||
// 기본 SELECT 컬럼들 (날짜는 YYYY-MM-DD 형식, 나머지는 TEXT 캐스팅)
|
||||
// 🔧 "*"는 전체 조회하되, 날짜 타입 타임존 문제를 피하기 위해
|
||||
// jsonb_build_object를 사용하여 명시적으로 변환
|
||||
let baseColumns: string;
|
||||
if (selectColumns.length === 1 && selectColumns[0] === "*") {
|
||||
// main.* 사용 시 날짜 타입 필드만 TO_CHAR로 변환
|
||||
// PostgreSQL의 날짜 → 타임스탬프 자동 변환으로 인한 타임존 문제 방지
|
||||
baseColumns = `main.*`;
|
||||
logger.info(
|
||||
`⚠️ [buildJoinQuery] main.* 사용 - 날짜 타임존 변환 주의 필요`
|
||||
);
|
||||
} else {
|
||||
baseColumns = selectColumns
|
||||
.map((col) => {
|
||||
const dataType = columnTypes?.get(col);
|
||||
const formattedCol = this.formatDateColumn("main", col, dataType);
|
||||
return `${formattedCol} AS ${col}`;
|
||||
})
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
// Entity 조인 컬럼들 (COALESCE로 NULL을 빈 문자열로 처리)
|
||||
// 별칭 매핑 생성 (JOIN 절과 동일한 로직)
|
||||
@@ -303,6 +333,13 @@ export class EntityJoinService {
|
||||
resultColumns.push(
|
||||
`COALESCE(${alias}.${col}::TEXT, '') AS ${config.sourceColumn}_label`
|
||||
);
|
||||
|
||||
// 🆕 referenceColumn (PK)도 항상 SELECT (parentDataMapping용)
|
||||
// 예: customer_code, item_number 등
|
||||
// col과 동일해도 별도의 alias로 추가 (customer_code as customer_code)
|
||||
resultColumns.push(
|
||||
`COALESCE(${alias}.${config.referenceColumn}::TEXT, '') AS ${config.referenceColumn}`
|
||||
);
|
||||
} else {
|
||||
resultColumns.push(
|
||||
`COALESCE(main.${col}::TEXT, '') AS ${config.aliasColumn}`
|
||||
@@ -328,6 +365,18 @@ export class EntityJoinService {
|
||||
.join(` || '${separator}' || `);
|
||||
|
||||
resultColumns.push(`(${concatParts}) AS ${config.aliasColumn}`);
|
||||
|
||||
// 🆕 referenceColumn (PK)도 함께 SELECT (parentDataMapping용)
|
||||
const isJoinTableColumn =
|
||||
config.referenceTable && config.referenceTable !== tableName;
|
||||
if (
|
||||
isJoinTableColumn &&
|
||||
!displayColumns.includes(config.referenceColumn)
|
||||
) {
|
||||
resultColumns.push(
|
||||
`COALESCE(${alias}.${config.referenceColumn}::TEXT, '') AS ${config.referenceColumn}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 모든 resultColumns를 반환
|
||||
|
||||
Reference in New Issue
Block a user