feat: Phase 3.16 데이터 관리 서비스 Raw Query 전환 완료
4개 서비스 18개 Prisma 호출 전환 완료: 1. **EnhancedDynamicFormService** (6개) - validateTableExists - information_schema 조회 - getTableColumns - 테이블 컬럼 정보 조회 with 캐싱 - getColumnWebTypes - 웹타입 정보 조회 - getPrimaryKeys - Primary Key 조회 - performInsert - 동적 INSERT with RETURNING - performUpdate - 동적 UPDATE with RETURNING 2. **DataMappingService** (5개) - getSourceData - 소스 테이블 데이터 조회 - executeInsert - 동적 INSERT - executeUpsert - ON CONFLICT DO UPDATE - executeUpdate - 동적 UPDATE - disconnect - 제거 (Raw Query 불필요) 3. **DataService** (4개) - getTableData - 동적 SELECT with 동적 WHERE/ORDER BY - checkTableExists - information_schema 테이블 존재 확인 - getTableColumnsSimple - 컬럼 정보 조회 - getColumnLabel - 컬럼 라벨 조회 4. **AdminService** (3개) - getAdminMenuList - WITH RECURSIVE 쿼리 - getUserMenuList - WITH RECURSIVE 쿼리 - getMenuInfo - LEFT JOIN으로 회사 정보 포함 기술적 성과: - 변수명 충돌 해결 (query vs sql) - WITH RECURSIVE 쿼리 전환 - Prisma include → LEFT JOIN 전환 - 동적 쿼리 생성 (WHERE, ORDER BY) - SQL 인젝션 방지 (컬럼명 검증) 진행률: Phase 3 173/186 (93.0%) 문서: PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
// 🔧 Prisma 클라이언트 중복 생성 방지 - 기존 인스턴스 재사용
|
||||
import prisma = require("../config/database");
|
||||
import { query, queryOne } from "../database/db";
|
||||
|
||||
export class AdminService {
|
||||
/**
|
||||
@@ -13,9 +11,9 @@ export class AdminService {
|
||||
|
||||
const { userLang = "ko" } = paramMap;
|
||||
|
||||
// 기존 Java의 selectAdminMenuList 쿼리를 Prisma로 포팅
|
||||
// WITH RECURSIVE 쿼리를 Prisma의 $queryRaw로 구현
|
||||
const menuList = await prisma.$queryRaw<any[]>`
|
||||
// 기존 Java의 selectAdminMenuList 쿼리를 Raw Query로 포팅
|
||||
// WITH RECURSIVE 쿼리 구현
|
||||
const menuList = await query<any>(`
|
||||
WITH RECURSIVE v_menu(
|
||||
LEVEL,
|
||||
MENU_TYPE,
|
||||
@@ -62,14 +60,14 @@ export class AdminService {
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU.LANG_KEY
|
||||
AND (MLKM.company_code = MENU.COMPANY_CODE OR (MENU.COMPANY_CODE IS NULL AND MLKM.company_code = '*'))
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
(SELECT MLT.lang_text
|
||||
FROM MULTI_LANG_KEY_MASTER MLKM
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU.LANG_KEY
|
||||
AND MLKM.company_code = '*'
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
MENU.MENU_NAME_KOR
|
||||
),
|
||||
@@ -80,14 +78,14 @@ export class AdminService {
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU.LANG_KEY_DESC
|
||||
AND (MLKM.company_code = MENU.COMPANY_CODE OR (MENU.COMPANY_CODE IS NULL AND MLKM.company_code = '*'))
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
(SELECT MLT.lang_text
|
||||
FROM MULTI_LANG_KEY_MASTER MLKM
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU.LANG_KEY_DESC
|
||||
AND MLKM.company_code = '*'
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
MENU.MENU_DESC
|
||||
)
|
||||
@@ -125,14 +123,14 @@ export class AdminService {
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU_SUB.LANG_KEY
|
||||
AND (MLKM.company_code = MENU_SUB.COMPANY_CODE OR (MENU_SUB.COMPANY_CODE IS NULL AND MLKM.company_code = '*'))
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
(SELECT MLT.lang_text
|
||||
FROM MULTI_LANG_KEY_MASTER MLKM
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU_SUB.LANG_KEY
|
||||
AND MLKM.company_code = '*'
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
MENU_SUB.MENU_NAME_KOR
|
||||
),
|
||||
@@ -143,14 +141,14 @@ export class AdminService {
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU_SUB.LANG_KEY_DESC
|
||||
AND (MLKM.company_code = MENU_SUB.COMPANY_CODE OR (MENU_SUB.COMPANY_CODE IS NULL AND MLKM.company_code = '*'))
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
(SELECT MLT.lang_text
|
||||
FROM MULTI_LANG_KEY_MASTER MLKM
|
||||
JOIN MULTI_LANG_TEXT MLT ON MLKM.key_id = MLT.key_id
|
||||
WHERE MLKM.lang_key = MENU_SUB.LANG_KEY_DESC
|
||||
AND MLKM.company_code = '*'
|
||||
AND MLT.lang_code = ${userLang}
|
||||
AND MLT.lang_code = $1
|
||||
LIMIT 1),
|
||||
MENU_SUB.MENU_DESC
|
||||
)
|
||||
@@ -190,7 +188,7 @@ export class AdminService {
|
||||
LEFT JOIN COMPANY_MNG CM ON A.COMPANY_CODE = CM.COMPANY_CODE
|
||||
WHERE 1 = 1
|
||||
ORDER BY PATH, SEQ
|
||||
`;
|
||||
`, [userLang]);
|
||||
|
||||
logger.info(`관리자 메뉴 목록 조회 결과: ${menuList.length}개`);
|
||||
if (menuList.length > 0) {
|
||||
@@ -213,8 +211,8 @@ export class AdminService {
|
||||
|
||||
const { userLang = "ko" } = paramMap;
|
||||
|
||||
// 기존 Java의 selectUserMenuList 쿼리를 Prisma로 포팅
|
||||
const menuList = await prisma.$queryRaw<any[]>`
|
||||
// 기존 Java의 selectUserMenuList 쿼리를 Raw Query로 포팅
|
||||
const menuList = await query<any>(`
|
||||
WITH RECURSIVE v_menu(
|
||||
LEVEL,
|
||||
MENU_TYPE,
|
||||
@@ -310,12 +308,12 @@ export class AdminService {
|
||||
FROM v_menu A
|
||||
LEFT JOIN COMPANY_MNG CM ON A.COMPANY_CODE = CM.COMPANY_CODE
|
||||
LEFT JOIN MULTI_LANG_KEY_MASTER MLKM_NAME ON A.LANG_KEY = MLKM_NAME.lang_key
|
||||
LEFT JOIN MULTI_LANG_TEXT MLT_NAME ON MLKM_NAME.key_id = MLT_NAME.key_id AND MLT_NAME.lang_code = ${userLang}
|
||||
LEFT JOIN MULTI_LANG_TEXT MLT_NAME ON MLKM_NAME.key_id = MLT_NAME.key_id AND MLT_NAME.lang_code = $1
|
||||
LEFT JOIN MULTI_LANG_KEY_MASTER MLKM_DESC ON A.LANG_KEY_DESC = MLKM_DESC.lang_key
|
||||
LEFT JOIN MULTI_LANG_TEXT MLT_DESC ON MLKM_DESC.key_id = MLT_DESC.key_id AND MLT_DESC.lang_code = ${userLang}
|
||||
LEFT JOIN MULTI_LANG_TEXT MLT_DESC ON MLKM_DESC.key_id = MLT_DESC.key_id AND MLT_DESC.lang_code = $1
|
||||
WHERE 1 = 1
|
||||
ORDER BY PATH, SEQ
|
||||
`;
|
||||
`, [userLang]);
|
||||
|
||||
logger.info(`사용자 메뉴 목록 조회 결과: ${menuList.length}개`);
|
||||
if (menuList.length > 0) {
|
||||
@@ -336,32 +334,31 @@ export class AdminService {
|
||||
try {
|
||||
logger.info(`AdminService.getMenuInfo 시작 - menuId: ${menuId}`);
|
||||
|
||||
// Prisma ORM을 사용한 메뉴 정보 조회 (회사 정보 포함)
|
||||
const menuInfo = await prisma.menu_info.findUnique({
|
||||
where: {
|
||||
objid: Number(menuId),
|
||||
},
|
||||
include: {
|
||||
company: {
|
||||
select: {
|
||||
company_name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
// Raw Query를 사용한 메뉴 정보 조회 (회사 정보 포함)
|
||||
const menuResult = await query<any>(
|
||||
`SELECT
|
||||
m.*,
|
||||
c.company_name
|
||||
FROM menu_info m
|
||||
LEFT JOIN company_mng c ON m.company_code = c.company_code
|
||||
WHERE m.objid = $1::numeric`,
|
||||
[menuId]
|
||||
);
|
||||
|
||||
if (!menuInfo) {
|
||||
if (!menuResult || menuResult.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const menuInfo = menuResult[0];
|
||||
|
||||
// 응답 형식 조정 (기존 형식과 호환성 유지)
|
||||
const result = {
|
||||
...menuInfo,
|
||||
objid: menuInfo.objid.toString(), // BigInt를 문자열로 변환
|
||||
objid: menuInfo.objid?.toString(),
|
||||
menu_type: menuInfo.menu_type?.toString(),
|
||||
parent_obj_id: menuInfo.parent_obj_id?.toString(),
|
||||
seq: menuInfo.seq?.toString(),
|
||||
company_name: menuInfo.company?.company_name || "미지정",
|
||||
company_name: menuInfo.company_name || "미지정",
|
||||
};
|
||||
|
||||
logger.info("메뉴 정보 조회 결과:", result);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { query } from "../database/db";
|
||||
import {
|
||||
DataMappingConfig,
|
||||
InboundMapping,
|
||||
@@ -11,10 +11,8 @@ import {
|
||||
} from "../types/dataMappingTypes";
|
||||
|
||||
export class DataMappingService {
|
||||
private prisma: PrismaClient;
|
||||
|
||||
constructor() {
|
||||
this.prisma = new PrismaClient();
|
||||
// No prisma instance needed
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,10 +402,10 @@ export class DataMappingService {
|
||||
}
|
||||
|
||||
// Raw SQL을 사용한 동적 쿼리
|
||||
const query = `SELECT * FROM ${tableName}${mapping.sourceFilter ? ` WHERE ${mapping.sourceFilter}` : ""}`;
|
||||
console.log(`🔍 [DataMappingService] 쿼리 실행: ${query}`);
|
||||
const sql = `SELECT * FROM ${tableName}${mapping.sourceFilter ? ` WHERE ${mapping.sourceFilter}` : ""}`;
|
||||
console.log(`🔍 [DataMappingService] 쿼리 실행: ${sql}`);
|
||||
|
||||
const result = await this.prisma.$queryRawUnsafe(query);
|
||||
const result = await query<any>(sql, []);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
@@ -429,14 +427,14 @@ export class DataMappingService {
|
||||
const values = Object.values(data);
|
||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||
|
||||
const query = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
const sql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
|
||||
console.log(`📝 [DataMappingService] INSERT 실행:`, {
|
||||
table: tableName,
|
||||
columns,
|
||||
query,
|
||||
query: sql,
|
||||
});
|
||||
await this.prisma.$executeRawUnsafe(query, ...values);
|
||||
await query(sql, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,7 +458,7 @@ export class DataMappingService {
|
||||
.map((col) => `${col} = EXCLUDED.${col}`)
|
||||
.join(", ");
|
||||
|
||||
const query = `
|
||||
const sql = `
|
||||
INSERT INTO ${tableName} (${columns.join(", ")})
|
||||
VALUES (${placeholders})
|
||||
ON CONFLICT (${keyFields.join(", ")})
|
||||
@@ -470,9 +468,9 @@ export class DataMappingService {
|
||||
console.log(`🔄 [DataMappingService] UPSERT 실행:`, {
|
||||
table: tableName,
|
||||
keyFields,
|
||||
query,
|
||||
query: sql,
|
||||
});
|
||||
await this.prisma.$executeRawUnsafe(query, ...values);
|
||||
await query(sql, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,14 +501,14 @@ export class DataMappingService {
|
||||
...keyFields.map((field) => data[field]),
|
||||
];
|
||||
|
||||
const query = `UPDATE ${tableName} SET ${updateClauses} WHERE ${whereConditions}`;
|
||||
const sql = `UPDATE ${tableName} SET ${updateClauses} WHERE ${whereConditions}`;
|
||||
|
||||
console.log(`✏️ [DataMappingService] UPDATE 실행:`, {
|
||||
table: tableName,
|
||||
keyFields,
|
||||
query,
|
||||
query: sql,
|
||||
});
|
||||
await this.prisma.$executeRawUnsafe(query, ...values);
|
||||
await query(sql, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,6 +568,6 @@ export class DataMappingService {
|
||||
* 리소스 정리
|
||||
*/
|
||||
async disconnect(): Promise<void> {
|
||||
await this.prisma.$disconnect();
|
||||
// No disconnect needed for raw queries
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import prisma from "../config/database";
|
||||
import { query, queryOne } from "../database/db";
|
||||
|
||||
interface GetTableDataParams {
|
||||
tableName: string;
|
||||
@@ -111,7 +110,7 @@ class DataService {
|
||||
}
|
||||
|
||||
// 동적 SQL 쿼리 생성
|
||||
let query = `SELECT * FROM "${tableName}"`;
|
||||
let sql = `SELECT * FROM "${tableName}"`;
|
||||
const queryParams: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
@@ -150,7 +149,7 @@ class DataService {
|
||||
|
||||
// WHERE 절 추가
|
||||
if (whereConditions.length > 0) {
|
||||
query += ` WHERE ${whereConditions.join(" AND ")}`;
|
||||
sql += ` WHERE ${whereConditions.join(" AND ")}`;
|
||||
}
|
||||
|
||||
// ORDER BY 절 추가
|
||||
@@ -162,7 +161,7 @@ class DataService {
|
||||
|
||||
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(columnName)) {
|
||||
const validDirection = direction === "DESC" ? "DESC" : "ASC";
|
||||
query += ` ORDER BY "${columnName}" ${validDirection}`;
|
||||
sql += ` ORDER BY "${columnName}" ${validDirection}`;
|
||||
}
|
||||
} else {
|
||||
// 기본 정렬: 최신순 (가능한 컬럼 시도)
|
||||
@@ -179,23 +178,23 @@ class DataService {
|
||||
);
|
||||
|
||||
if (availableDateColumn) {
|
||||
query += ` ORDER BY "${availableDateColumn}" DESC`;
|
||||
sql += ` ORDER BY "${availableDateColumn}" DESC`;
|
||||
}
|
||||
}
|
||||
|
||||
// LIMIT과 OFFSET 추가
|
||||
query += ` LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`;
|
||||
sql += ` LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`;
|
||||
queryParams.push(limit, offset);
|
||||
|
||||
console.log("🔍 실행할 쿼리:", query);
|
||||
console.log("🔍 실행할 쿼리:", sql);
|
||||
console.log("📊 쿼리 파라미터:", queryParams);
|
||||
|
||||
// 쿼리 실행
|
||||
const result = await prisma.$queryRawUnsafe(query, ...queryParams);
|
||||
const result = await query<any>(sql, queryParams);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: result as any[],
|
||||
data: result,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`데이터 조회 오류 (${tableName}):`, error);
|
||||
@@ -259,18 +258,16 @@ class DataService {
|
||||
*/
|
||||
private async checkTableExists(tableName: string): Promise<boolean> {
|
||||
try {
|
||||
const result = await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT EXISTS (
|
||||
const result = await query<{ exists: boolean }>(
|
||||
`SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = $1
|
||||
);
|
||||
`,
|
||||
tableName
|
||||
)`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
return (result as any)[0]?.exists || false;
|
||||
return result[0]?.exists || false;
|
||||
} catch (error) {
|
||||
console.error("테이블 존재 확인 오류:", error);
|
||||
return false;
|
||||
@@ -281,18 +278,16 @@ class DataService {
|
||||
* 테이블 컬럼 정보 조회 (간단 버전)
|
||||
*/
|
||||
private async getTableColumnsSimple(tableName: string): Promise<any[]> {
|
||||
const result = await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT column_name, data_type, is_nullable, column_default
|
||||
const result = await query<any>(
|
||||
`SELECT column_name, data_type, is_nullable, column_default
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = $1
|
||||
AND table_schema = 'public'
|
||||
ORDER BY ordinal_position;
|
||||
`,
|
||||
tableName
|
||||
ORDER BY ordinal_position`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
return result as any[];
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,19 +299,15 @@ class DataService {
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
// column_labels 테이블에서 라벨 조회
|
||||
const result = await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT label_ko
|
||||
const result = await query<{ label_ko: string }>(
|
||||
`SELECT label_ko
|
||||
FROM column_labels
|
||||
WHERE table_name = $1 AND column_name = $2
|
||||
LIMIT 1;
|
||||
`,
|
||||
tableName,
|
||||
columnName
|
||||
LIMIT 1`,
|
||||
[tableName, columnName]
|
||||
);
|
||||
|
||||
const labelResult = result as any[];
|
||||
return labelResult[0]?.label_ko || null;
|
||||
return result[0]?.label_ko || null;
|
||||
} catch (error) {
|
||||
// column_labels 테이블이 없거나 오류가 발생하면 null 반환
|
||||
return null;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* 타입 안전성과 검증 강화
|
||||
*/
|
||||
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { query, queryOne } from "../database/db";
|
||||
import {
|
||||
WebType,
|
||||
DynamicWebType,
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
} from "../types/unified-web-types";
|
||||
import { DataflowControlService } from "./dataflowControlService";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// 테이블 컬럼 정보
|
||||
export interface TableColumn {
|
||||
column_name: string;
|
||||
@@ -156,17 +154,15 @@ export class EnhancedDynamicFormService {
|
||||
*/
|
||||
private async validateTableExists(tableName: string): Promise<boolean> {
|
||||
try {
|
||||
const result = await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT EXISTS (
|
||||
const result = await query<{ exists: boolean }>(
|
||||
`SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_name = $1
|
||||
) as exists
|
||||
`,
|
||||
tableName
|
||||
) as exists`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
return (result as any)[0]?.exists || false;
|
||||
return result[0]?.exists || false;
|
||||
} catch (error) {
|
||||
console.error(`❌ 테이블 존재 여부 확인 실패: ${tableName}`, error);
|
||||
return false;
|
||||
@@ -184,9 +180,8 @@ export class EnhancedDynamicFormService {
|
||||
}
|
||||
|
||||
try {
|
||||
const columns = (await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT
|
||||
const columns = await query<TableColumn>(
|
||||
`SELECT
|
||||
column_name,
|
||||
data_type,
|
||||
is_nullable,
|
||||
@@ -196,10 +191,9 @@ export class EnhancedDynamicFormService {
|
||||
numeric_scale
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = $1
|
||||
ORDER BY ordinal_position
|
||||
`,
|
||||
tableName
|
||||
)) as TableColumn[];
|
||||
ORDER BY ordinal_position`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
// 캐시 저장 (10분)
|
||||
this.columnCache.set(tableName, columns);
|
||||
@@ -226,18 +220,21 @@ export class EnhancedDynamicFormService {
|
||||
|
||||
try {
|
||||
// table_type_columns에서 웹타입 정보 조회
|
||||
const webTypeData = (await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT
|
||||
const webTypeData = await query<{
|
||||
column_name: string;
|
||||
web_type: string;
|
||||
is_nullable: string;
|
||||
detail_settings: any;
|
||||
}>(
|
||||
`SELECT
|
||||
column_name,
|
||||
web_type,
|
||||
is_nullable,
|
||||
detail_settings
|
||||
FROM table_type_columns
|
||||
WHERE table_name = $1
|
||||
`,
|
||||
tableName
|
||||
)) as any[];
|
||||
WHERE table_name = $1`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
const columnWebTypes: ColumnWebTypeInfo[] = webTypeData.map((row) => ({
|
||||
columnName: row.column_name,
|
||||
@@ -555,15 +552,13 @@ export class EnhancedDynamicFormService {
|
||||
*/
|
||||
private async getPrimaryKeys(tableName: string): Promise<string[]> {
|
||||
try {
|
||||
const result = (await prisma.$queryRawUnsafe(
|
||||
`
|
||||
SELECT column_name
|
||||
const result = await query<{ column_name: string }>(
|
||||
`SELECT column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_name = $1
|
||||
AND constraint_name LIKE '%_pkey'
|
||||
`,
|
||||
tableName
|
||||
)) as any[];
|
||||
AND constraint_name LIKE '%_pkey'`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
return result.map((row) => row.column_name);
|
||||
} catch (error) {
|
||||
@@ -594,10 +589,7 @@ export class EnhancedDynamicFormService {
|
||||
query: insertQuery.replace(/\n\s+/g, " "),
|
||||
});
|
||||
|
||||
const result = (await prisma.$queryRawUnsafe(
|
||||
insertQuery,
|
||||
...values
|
||||
)) as any[];
|
||||
const result = await query<any>(insertQuery, values);
|
||||
|
||||
return {
|
||||
data: result[0],
|
||||
@@ -649,10 +641,7 @@ export class EnhancedDynamicFormService {
|
||||
query: updateQuery.replace(/\n\s+/g, " "),
|
||||
});
|
||||
|
||||
const result = (await prisma.$queryRawUnsafe(
|
||||
updateQuery,
|
||||
...updateValues
|
||||
)) as any[];
|
||||
const result = await query<any>(updateQuery, updateValues);
|
||||
|
||||
return {
|
||||
data: result[0],
|
||||
|
||||
Reference in New Issue
Block a user