diff options
Diffstat (limited to 'lib/filter-columns.ts')
| -rw-r--r-- | lib/filter-columns.ts | 139 |
1 files changed, 115 insertions, 24 deletions
diff --git a/lib/filter-columns.ts b/lib/filter-columns.ts index 4b995925..4e561d05 100644 --- a/lib/filter-columns.ts +++ b/lib/filter-columns.ts @@ -22,39 +22,48 @@ import type { PgTable, PgView } from "drizzle-orm/pg-core" type TableOrView = PgTable | PgView<any> +// 조인된 테이블들의 타입 정의 +export interface JoinedTables { + [key: string]: TableOrView +} + +// 커스텀 컬럼 매핑 타입 정의 +export interface CustomColumnMapping { + [filterId: string]: { + table: TableOrView + column: string + } | AnyColumn +} + /** - * Construct SQL conditions based on the provided filters for a specific table. - * - * This function takes a table and an array of filters, and returns a SQL - * expression that represents the logical combination of these conditions. The conditions - * are combined using the specified join operator (either 'AND' or 'OR'), which is determined - * by the first filter's joinOperator property. - * - * Each filter can specify various operators (e.g., equality, inequality, - * comparison for numbers and dates, etc.) and the function will generate the appropriate - * SQL expressions based on the filter's type and value. - * - * @param table - The table to apply the filters on. - * @param filters - An array of filters to be applied to the table. - * @param joinOperator - The join operator to use for combining the filters. - * @returns A SQL expression representing the combined filters, or undefined if no valid - * filters are found. + * Enhanced filterColumns function that supports joined tables and custom column mapping. + * + * This function can handle filters that reference columns from different tables + * in a joined query, and allows for custom mapping of filter IDs to actual table columns. */ - export function filterColumns<T extends TableOrView>({ table, filters, joinOperator, + joinedTables, + customColumnMapping, }: { table: T filters: Filter<T>[] joinOperator: JoinOperator + joinedTables?: JoinedTables + customColumnMapping?: CustomColumnMapping }): SQL | undefined { const joinFn = joinOperator === "and" ? and : or const conditions = filters.map((filter) => { - const column = getColumn(table, filter.id) + const column = getColumnWithMapping(table, filter.id, joinedTables, customColumnMapping) + + if (!column) { + console.warn(`Column not found for filter ID: ${filter.id}`) + return undefined + } switch (filter.operator) { case "eq": @@ -174,20 +183,102 @@ export function filterColumns<T extends TableOrView>({ (condition) => condition !== undefined ) - return validConditions.length > 0 ? joinFn(...validConditions) : undefined } /** - * Get table column. - * @param table The table to get the column from. - * @param columnKey The key of the column to retrieve from the table. - * @returns The column corresponding to the provided key. + * Enhanced column getter - 간단한 수정 버전 */ +function getColumnWithMapping<T extends TableOrView>( + table: T, + columnKey: keyof T | string, + joinedTables?: JoinedTables, + customColumnMapping?: CustomColumnMapping +): AnyColumn | undefined { + + // 1. 커스텀 매핑이 있는 경우 우선 확인 + if (customColumnMapping && columnKey in customColumnMapping) { + const mapping = customColumnMapping[columnKey as string] + + if (typeof mapping === 'object' && 'dataType' in mapping) { + return mapping as AnyColumn + } + + if (typeof mapping === 'object' && 'table' in mapping && 'column' in mapping) { + try { + if (mapping.table && typeof mapping.column === 'string') { + const column = (mapping.table as any)[mapping.column]; + if (column !== undefined) { + return column as AnyColumn; + } + } + } catch (error) { + console.warn(`Failed to get column ${mapping.column} from table:`, error) + } + } + } + + // 2. 메인 테이블에서 컬럼 찾기 - 수정된 부분 + if (typeof columnKey === 'string') { + // ✅ in 연산자 대신 직접 접근해서 undefined 체크 + try { + const column = (table as any)[columnKey]; + if (column !== undefined && column !== null) { + return column as AnyColumn; + } + } catch (error) { + // 직접 접근 실패 시 조용히 넘어감 + } + } else { + // keyof T 타입인 경우 기존 함수 사용 + try { + return getColumn(table, columnKey); + } catch (error) { + // getColumn 실패 시 조용히 넘어감 + } + } + + // 3. 조인된 테이블들에서 컬럼 찾기 + if (joinedTables && typeof columnKey === 'string') { + for (const [tableName, joinedTable] of Object.entries(joinedTables)) { + try { + const column = (joinedTable as any)[columnKey]; + if (column !== undefined && column !== null) { + return column as AnyColumn; + } + } catch (error) { + // 조용히 넘어감 + } + } + } + + // 4. 컬럼을 찾지 못한 경우 + return undefined; +} +/** + * Get table column (기존 함수 유지). + */ export function getColumn<T extends TableOrView>( table: T, columnKey: keyof T ): AnyColumn { return table[columnKey] as AnyColumn -}
\ No newline at end of file +} + +/** + * Safe helper to get column from any table with string key + */ +export function getColumnSafe(table: TableOrView, columnKey: string): AnyColumn | undefined { + try { + if (columnKey in table) { + return (table as any)[columnKey] as AnyColumn + } + } catch (error) { + console.warn(`Failed to get column ${columnKey} from table:`, error) + } + return undefined +} + +// 사용 예시를 위한 타입 정의 +export type FilterColumnsParams<T extends TableOrView> = Parameters<typeof filterColumns<T>>[0]
\ No newline at end of file |
