diff --git a/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md b/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md index 457e0dd4..c598975c 100644 --- a/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md +++ b/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md @@ -6,16 +6,71 @@ ### ๐Ÿ“Š ๊ธฐ๋ณธ ์ •๋ณด -| ํ•ญ๋ชฉ | ๋‚ด์šฉ | -| --------------- | ------------------------------------------------------------------------- | -| ๋Œ€์ƒ ์„œ๋น„์Šค | 4๊ฐœ (EnhancedDynamicForm, DataMapping, Data, Admin) | -| ํŒŒ์ผ ์œ„์น˜ | `backend-node/src/services/{enhanced,data,admin}*.ts` | -| ์ด ํŒŒ์ผ ํฌ๊ธฐ | 2,062 ๋ผ์ธ | -| Prisma ํ˜ธ์ถœ | 18๊ฐœ | -| **ํ˜„์žฌ ์ง„ํ–‰๋ฅ ** | **0/18 (0%)** ๐Ÿ”„ **์ง„ํ–‰ ์˜ˆ์ •** | -| ๋ณต์žก๋„ | ์ค‘๊ฐ„ (๋™์  ์ฟผ๋ฆฌ, JSON ํ•„๋“œ, ๊ด€๋ฆฌ์ž ๊ธฐ๋Šฅ) | -| ์šฐ์„ ์ˆœ์œ„ | ๐ŸŸก ์ค‘๊ฐ„ (Phase 3.16) | -| **์ƒํƒœ** | โณ **๋Œ€๊ธฐ ์ค‘** | +| ํ•ญ๋ชฉ | ๋‚ด์šฉ | +| --------------- | ----------------------------------------------------- | +| ๋Œ€์ƒ ์„œ๋น„์Šค | 4๊ฐœ (EnhancedDynamicForm, DataMapping, Data, Admin) | +| ํŒŒ์ผ ์œ„์น˜ | `backend-node/src/services/{enhanced,data,admin}*.ts` | +| ์ด ํŒŒ์ผ ํฌ๊ธฐ | 2,062 ๋ผ์ธ | +| Prisma ํ˜ธ์ถœ | 0๊ฐœ (์ „ํ™˜ ์™„๋ฃŒ) | +| **ํ˜„์žฌ ์ง„ํ–‰๋ฅ ** | **18/18 (100%)** โœ… **์ „ํ™˜ ์™„๋ฃŒ** | +| ๋ณต์žก๋„ | ์ค‘๊ฐ„ (๋™์  ์ฟผ๋ฆฌ, JSON ํ•„๋“œ, ๊ด€๋ฆฌ์ž ๊ธฐ๋Šฅ) | +| ์šฐ์„ ์ˆœ์œ„ | ๐ŸŸก ์ค‘๊ฐ„ (Phase 3.16) | +| **์ƒํƒœ** | โœ… **์™„๋ฃŒ** | + +--- + +## โœ… ์ „ํ™˜ ์™„๋ฃŒ ๋‚ด์—ญ + +### ์ „ํ™˜๋œ Prisma ํ˜ธ์ถœ (18๊ฐœ) + +#### 1. EnhancedDynamicFormService (6๊ฐœ) +- `validateTableExists()` - $queryRawUnsafe โ†’ query +- `getTableColumns()` - $queryRawUnsafe โ†’ query +- `getColumnWebTypes()` - $queryRawUnsafe โ†’ query +- `getPrimaryKeys()` - $queryRawUnsafe โ†’ query +- `performInsert()` - $queryRawUnsafe โ†’ query +- `performUpdate()` - $queryRawUnsafe โ†’ query + +#### 2. DataMappingService (5๊ฐœ) +- `getSourceData()` - $queryRawUnsafe โ†’ query +- `executeInsert()` - $executeRawUnsafe โ†’ query +- `executeUpsert()` - $executeRawUnsafe โ†’ query +- `executeUpdate()` - $executeRawUnsafe โ†’ query +- `disconnect()` - ์ œ๊ฑฐ (Raw Query๋Š” disconnect ๋ถˆํ•„์š”) + +#### 3. DataService (4๊ฐœ) +- `getTableData()` - $queryRawUnsafe โ†’ query +- `checkTableExists()` - $queryRawUnsafe โ†’ query +- `getTableColumnsSimple()` - $queryRawUnsafe โ†’ query +- `getColumnLabel()` - $queryRawUnsafe โ†’ query + +#### 4. AdminService (3๊ฐœ) +- `getAdminMenuList()` - $queryRaw โ†’ query (WITH RECURSIVE) +- `getUserMenuList()` - $queryRaw โ†’ query (WITH RECURSIVE) +- `getMenuInfo()` - findUnique โ†’ query (JOIN) + +### ์ฃผ์š” ๊ธฐ์ˆ ์  ํ•ด๊ฒฐ ์‚ฌํ•ญ + +1. **๋ณ€์ˆ˜๋ช… ์ถฉ๋Œ ํ•ด๊ฒฐ** + - `dataService.ts`์—์„œ `query` ๋ณ€์ˆ˜ โ†’ `sql` ๋ณ€์ˆ˜๋กœ ๋ณ€๊ฒฝ + - `query()` ํ•จ์ˆ˜์™€ ๋กœ์ปฌ ๋ณ€์ˆ˜ ์ถฉ๋Œ ๋ฐฉ์ง€ + +2. **WITH RECURSIVE ์ฟผ๋ฆฌ ์ „ํ™˜** + - Prisma์˜ `$queryRaw` ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด โ†’ ์ผ๋ฐ˜ ๋ฌธ์ž์—ด + - `${userLang}` โ†’ `$1` ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ + +3. **JOIN ์ฟผ๋ฆฌ ์ „ํ™˜** + - Prisma์˜ `include` ์˜ต์…˜ โ†’ `LEFT JOIN` ์ฟผ๋ฆฌ + - ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹จ์ผ ์ฟผ๋ฆฌ๋กœ ์กฐํšŒ + +4. **๋™์  ์ฟผ๋ฆฌ ์ƒ์„ฑ** + - ๋™์  WHERE ์กฐ๊ฑด ๊ตฌ์„ฑ + - SQL ์ธ์ ์…˜ ๋ฐฉ์ง€ (์ปฌ๋Ÿผ๋ช… ๊ฒ€์ฆ) + - ๋™์  ORDER BY ์ฒ˜๋ฆฌ + +### ์ปดํŒŒ์ผ ์ƒํƒœ +โœ… TypeScript ์ปดํŒŒ์ผ ์„ฑ๊ณต +โœ… Linter ์˜ค๋ฅ˜ ์—†์Œ --- @@ -24,12 +79,14 @@ ### 1. EnhancedDynamicFormService (6๊ฐœ ํ˜ธ์ถœ, 786 ๋ผ์ธ) **์ฃผ์š” ๊ธฐ๋Šฅ**: + - ๊ณ ๊ธ‰ ๋™์  ํผ ๊ด€๋ฆฌ - ํผ ๊ฒ€์ฆ ๊ทœ์น™ - ์กฐ๊ฑด๋ถ€ ํ•„๋“œ ํ‘œ์‹œ - ํผ ํ…œํ”Œ๋ฆฟ ๊ด€๋ฆฌ **์˜ˆ์ƒ Prisma ํ˜ธ์ถœ**: + - `getEnhancedForms()` - ๊ณ ๊ธ‰ ํผ ๋ชฉ๋ก ์กฐํšŒ - `getEnhancedForm()` - ๊ณ ๊ธ‰ ํผ ๋‹จ๊ฑด ์กฐํšŒ - `createEnhancedForm()` - ๊ณ ๊ธ‰ ํผ ์ƒ์„ฑ @@ -38,6 +95,7 @@ - `getFormValidationRules()` - ๊ฒ€์ฆ ๊ทœ์น™ ์กฐํšŒ **๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ**: + - JSON ํ•„๋“œ (validation_rules, conditional_logic, field_config) - ๋ณต์žกํ•œ ๊ฒ€์ฆ ๊ทœ์น™ - ๋™์  ํ•„๋“œ ์ƒ์„ฑ @@ -48,12 +106,14 @@ ### 2. DataMappingService (5๊ฐœ ํ˜ธ์ถœ, 575 ๋ผ์ธ) **์ฃผ์š” ๊ธฐ๋Šฅ**: + - ๋ฐ์ดํ„ฐ ๋งคํ•‘ ์„ค์ • ๊ด€๋ฆฌ - ์†Œ์Šค-ํƒ€๊ฒŸ ํ•„๋“œ ๋งคํ•‘ - ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๊ทœ์น™ - ๋งคํ•‘ ์‹คํ–‰ **์˜ˆ์ƒ Prisma ํ˜ธ์ถœ**: + - `getDataMappings()` - ๋งคํ•‘ ์„ค์ • ๋ชฉ๋ก ์กฐํšŒ - `getDataMapping()` - ๋งคํ•‘ ์„ค์ • ๋‹จ๊ฑด ์กฐํšŒ - `createDataMapping()` - ๋งคํ•‘ ์„ค์ • ์ƒ์„ฑ @@ -61,6 +121,7 @@ - `deleteDataMapping()` - ๋งคํ•‘ ์„ค์ • ์‚ญ์ œ **๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ**: + - JSON ํ•„๋“œ (field_mappings, transformation_rules) - ๋ณต์žกํ•œ ๋ณ€ํ™˜ ๋กœ์ง - ๋งคํ•‘ ๊ฒ€์ฆ @@ -71,18 +132,21 @@ ### 3. DataService (4๊ฐœ ํ˜ธ์ถœ, 327 ๋ผ์ธ) **์ฃผ์š” ๊ธฐ๋Šฅ**: + - ๋™์  ๋ฐ์ดํ„ฐ ์กฐํšŒ - ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง - ๋ฐ์ดํ„ฐ ์ •๋ ฌ - ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ **์˜ˆ์ƒ Prisma ํ˜ธ์ถœ**: + - `getDataByTable()` - ํ…Œ์ด๋ธ”๋ณ„ ๋ฐ์ดํ„ฐ ์กฐํšŒ - `getDataById()` - ๋ฐ์ดํ„ฐ ๋‹จ๊ฑด ์กฐํšŒ - `executeCustomQuery()` - ์ปค์Šคํ…€ ์ฟผ๋ฆฌ ์‹คํ–‰ - `getDataStatistics()` - ๋ฐ์ดํ„ฐ ํ†ต๊ณ„ ์กฐํšŒ **๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ**: + - ๋™์  ํ…Œ์ด๋ธ” ์ฟผ๋ฆฌ - SQL ์ธ์ ์…˜ ๋ฐฉ์ง€ - ๋™์  WHERE ์กฐ๊ฑด @@ -93,17 +157,20 @@ ### 4. AdminService (3๊ฐœ ํ˜ธ์ถœ, 374 ๋ผ์ธ) **์ฃผ์š” ๊ธฐ๋Šฅ**: + - ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด ๊ด€๋ฆฌ - ์‹œ์Šคํ…œ ์„ค์ • - ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ - ๋กœ๊ทธ ์กฐํšŒ **์˜ˆ์ƒ Prisma ํ˜ธ์ถœ**: + - `getAdminMenus()` - ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด ์กฐํšŒ - `getSystemSettings()` - ์‹œ์Šคํ…œ ์„ค์ • ์กฐํšŒ - `updateSystemSettings()` - ์‹œ์Šคํ…œ ์„ค์ • ์—…๋ฐ์ดํŠธ **๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ**: + - ๋ฉ”๋‰ด ๊ณ„์ธต ๊ตฌ์กฐ - ๊ถŒํ•œ ๊ธฐ๋ฐ˜ ํ•„ํ„ฐ๋ง - JSON ์„ค์ • ํ•„๋“œ @@ -114,17 +181,23 @@ ## ๐Ÿ’ก ํ†ตํ•ฉ ์ „ํ™˜ ์ „๋žต ### Phase 1: ๋‹จ์ˆœ CRUD ์ „ํ™˜ (12๊ฐœ) + **EnhancedDynamicFormService (6๊ฐœ) + DataMappingService (5๊ฐœ) + AdminService (1๊ฐœ)** + - ๊ธฐ๋ณธ CRUD ๊ธฐ๋Šฅ - JSON ํ•„๋“œ ์ฒ˜๋ฆฌ ### Phase 2: ๋™์  ์ฟผ๋ฆฌ ์ „ํ™˜ (4๊ฐœ) + **DataService (4๊ฐœ)** + - ๋™์  ํ…Œ์ด๋ธ” ์ฟผ๋ฆฌ - ๋ณด์•ˆ ๊ฒ€์ฆ ### Phase 3: ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ์ „ํ™˜ (2๊ฐœ) + **AdminService (2๊ฐœ)** + - ์‹œ์Šคํ…œ ์„ค์ • - ์บ์‹ฑ @@ -135,6 +208,7 @@ ### ์˜ˆ์‹œ 1: ๊ณ ๊ธ‰ ํผ ์ƒ์„ฑ (JSON ํ•„๋“œ) **๋ณ€๊ฒฝ ์ „**: + ```typescript const form = await prisma.enhanced_forms.create({ data: { @@ -149,6 +223,7 @@ const form = await prisma.enhanced_forms.create({ ``` **๋ณ€๊ฒฝ ํ›„**: + ```typescript const form = await queryOne( `INSERT INTO enhanced_forms @@ -170,6 +245,7 @@ const form = await queryOne( ### ์˜ˆ์‹œ 2: ๋ฐ์ดํ„ฐ ๋งคํ•‘ ์กฐํšŒ **๋ณ€๊ฒฝ ์ „**: + ```typescript const mappings = await prisma.data_mappings.findMany({ where: { @@ -185,6 +261,7 @@ const mappings = await prisma.data_mappings.findMany({ ``` **๋ณ€๊ฒฝ ํ›„**: + ```typescript const mappings = await query( `SELECT @@ -211,6 +288,7 @@ const mappings = await query( ### ์˜ˆ์‹œ 3: ๋™์  ํ…Œ์ด๋ธ” ์ฟผ๋ฆฌ (DataService) **๋ณ€๊ฒฝ ์ „**: + ```typescript // Prisma๋กœ๋Š” ๋™์  ํ…Œ์ด๋ธ” ์ฟผ๋ฆฌ ๋ถˆ๊ฐ€๋Šฅ // ์ด๋ฏธ $queryRawUnsafe ์‚ฌ์šฉ ์ค‘์ผ ๊ฐ€๋Šฅ์„ฑ @@ -221,6 +299,7 @@ const data = await prisma.$queryRawUnsafe( ``` **๋ณ€๊ฒฝ ํ›„**: + ```typescript // SQL ์ธ์ ์…˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ํ…Œ์ด๋ธ”๋ช… ๊ฒ€์ฆ const validTableName = validateTableName(tableName); @@ -234,6 +313,7 @@ const data = await query( ### ์˜ˆ์‹œ 4: ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด ์กฐํšŒ (๊ณ„์ธต ๊ตฌ์กฐ) **๋ณ€๊ฒฝ ์ „**: + ```typescript const menus = await prisma.admin_menus.findMany({ where: { is_active: true }, @@ -247,6 +327,7 @@ const menus = await prisma.admin_menus.findMany({ ``` **๋ณ€๊ฒฝ ํ›„**: + ```typescript // ์žฌ๊ท€ CTE๋ฅผ ์‚ฌ์šฉํ•œ ๊ณ„์ธต ์ฟผ๋ฆฌ const menus = await query( @@ -273,6 +354,7 @@ const menus = await query( ## ๐Ÿ”ง ๊ธฐ์ˆ ์  ๊ณ ๋ ค์‚ฌํ•ญ ### 1. JSON ํ•„๋“œ ์ฒ˜๋ฆฌ + ```typescript // ๋ณต์žกํ•œ JSON ๊ตฌ์กฐ interface ValidationRules { @@ -287,12 +369,14 @@ interface ValidationRules { JSON.stringify(validationRules); // ์กฐํšŒ ํ›„ -const parsed = typeof row.validation_rules === "string" - ? JSON.parse(row.validation_rules) - : row.validation_rules; +const parsed = + typeof row.validation_rules === "string" + ? JSON.parse(row.validation_rules) + : row.validation_rules; ``` ### 2. ๋™์  ํ…Œ์ด๋ธ” ์ฟผ๋ฆฌ ๋ณด์•ˆ + ```typescript // ํ…Œ์ด๋ธ”๋ช… ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ const ALLOWED_TABLES = ["users", "products", "orders"]; @@ -314,13 +398,14 @@ function validateColumnName(columnName: string): string { ``` ### 3. ์žฌ๊ท€ CTE (๊ณ„์ธต ๊ตฌ์กฐ) + ```sql WITH RECURSIVE hierarchy AS ( -- ์ตœ์ƒ์œ„ ๋…ธ๋“œ SELECT * FROM table WHERE parent_id IS NULL - + UNION ALL - + -- ํ•˜์œ„ ๋…ธ๋“œ SELECT t.* FROM table t JOIN hierarchy h ON t.parent_id = h.id @@ -329,8 +414,9 @@ SELECT * FROM hierarchy ``` ### 4. JSON ์ง‘๊ณ„ (๊ด€๊ณ„ ๋ฐ์ดํ„ฐ) + ```sql -SELECT +SELECT parent.*, COALESCE( json_agg( @@ -348,6 +434,7 @@ GROUP BY parent.id ## ๐Ÿ“ ์ „ํ™˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ### EnhancedDynamicFormService (6๊ฐœ) + - [ ] `getEnhancedForms()` - ๋ชฉ๋ก ์กฐํšŒ - [ ] `getEnhancedForm()` - ๋‹จ๊ฑด ์กฐํšŒ - [ ] `createEnhancedForm()` - ์ƒ์„ฑ (JSON ํ•„๋“œ) @@ -356,6 +443,7 @@ GROUP BY parent.id - [ ] `getFormValidationRules()` - ๊ฒ€์ฆ ๊ทœ์น™ ์กฐํšŒ ### DataMappingService (5๊ฐœ) + - [ ] `getDataMappings()` - ๋ชฉ๋ก ์กฐํšŒ - [ ] `getDataMapping()` - ๋‹จ๊ฑด ์กฐํšŒ - [ ] `createDataMapping()` - ์ƒ์„ฑ @@ -363,17 +451,20 @@ GROUP BY parent.id - [ ] `deleteDataMapping()` - ์‚ญ์ œ ### DataService (4๊ฐœ) + - [ ] `getDataByTable()` - ๋™์  ํ…Œ์ด๋ธ” ์กฐํšŒ - [ ] `getDataById()` - ๋‹จ๊ฑด ์กฐํšŒ - [ ] `executeCustomQuery()` - ์ปค์Šคํ…€ ์ฟผ๋ฆฌ - [ ] `getDataStatistics()` - ํ†ต๊ณ„ ์กฐํšŒ ### AdminService (3๊ฐœ) + - [ ] `getAdminMenus()` - ๋ฉ”๋‰ด ์กฐํšŒ (์žฌ๊ท€ CTE) - [ ] `getSystemSettings()` - ์‹œ์Šคํ…œ ์„ค์ • ์กฐํšŒ - [ ] `updateSystemSettings()` - ์‹œ์Šคํ…œ ์„ค์ • ์—…๋ฐ์ดํŠธ ### ๊ณตํ†ต ์ž‘์—… + - [ ] import ๋ฌธ ์ˆ˜์ • (๋ชจ๋“  ์„œ๋น„์Šค) - [ ] Prisma import ์™„์ „ ์ œ๊ฑฐ - [ ] JSON ํ•„๋“œ ์ฒ˜๋ฆฌ ํ™•์ธ @@ -384,15 +475,18 @@ GROUP BY parent.id ## ๐Ÿงช ํ…Œ์ŠคํŠธ ๊ณ„ํš ### ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (18๊ฐœ) + - ๊ฐ Prisma ํ˜ธ์ถœ๋ณ„ 1๊ฐœ์”ฉ ### ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (6๊ฐœ) + - EnhancedDynamicFormService: ํผ ์ƒ์„ฑ ๋ฐ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ (2๊ฐœ) - DataMappingService: ๋งคํ•‘ ์„ค์ • ๋ฐ ์‹คํ–‰ ํ…Œ์ŠคํŠธ (2๊ฐœ) - DataService: ๋™์  ์ฟผ๋ฆฌ ๋ฐ ๋ณด์•ˆ ํ…Œ์ŠคํŠธ (1๊ฐœ) - AdminService: ๋ฉ”๋‰ด ๊ณ„์ธต ๊ตฌ์กฐ ํ…Œ์ŠคํŠธ (1๊ฐœ) ### ๋ณด์•ˆ ํ…Œ์ŠคํŠธ + - SQL ์ธ์ ์…˜ ๋ฐฉ์ง€ ํ…Œ์ŠคํŠธ - ํ…Œ์ด๋ธ”๋ช… ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ - ์ปฌ๋Ÿผ๋ช… ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ @@ -406,7 +500,6 @@ GROUP BY parent.id - ๋™์  ์ฟผ๋ฆฌ ๋ณด์•ˆ - ์žฌ๊ท€ CTE - JSON ์ง‘๊ณ„ - - **์˜ˆ์ƒ ์†Œ์š” ์‹œ๊ฐ„**: 2.5~3์‹œ๊ฐ„ - Phase 1 (๊ธฐ๋ณธ CRUD): 1์‹œ๊ฐ„ - Phase 2 (๋™์  ์ฟผ๋ฆฌ): 1์‹œ๊ฐ„ @@ -418,6 +511,7 @@ GROUP BY parent.id ## โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ ### ๋ณด์•ˆ ํ•„์ˆ˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ + 1. โœ… ๋™์  ํ…Œ์ด๋ธ”๋ช…์€ ๋ฐ˜๋“œ์‹œ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ๊ฒ€์ฆ 2. โœ… ๋™์  ์ปฌ๋Ÿผ๋ช…์€ ์ •๊ทœ์‹์œผ๋กœ ๊ฒ€์ฆ 3. โœ… WHERE ์ ˆ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋ฐ˜๋“œ์‹œ ๋ฐ”์ธ๋”ฉ @@ -425,6 +519,7 @@ GROUP BY parent.id 5. โœ… ์žฌ๊ท€ ์ฟผ๋ฆฌ๋Š” ๊นŠ์ด ์ œํ•œ ์„ค์ • ### ์„ฑ๋Šฅ ์ตœ์ ํ™” + - JSON ํ•„๋“œ ์ธ๋ฑ์‹ฑ (GIN ์ธ๋ฑ์Šค) - ์žฌ๊ท€ ์ฟผ๋ฆฌ ๊นŠ์ด ์ œํ•œ - ์ง‘๊ณ„ ์ฟผ๋ฆฌ ์ตœ์ ํ™” @@ -435,4 +530,3 @@ GROUP BY parent.id **์ƒํƒœ**: โณ **๋Œ€๊ธฐ ์ค‘** **ํŠน์ด์‚ฌํ•ญ**: JSON ํ•„๋“œ, ๋™์  ์ฟผ๋ฆฌ, ์žฌ๊ท€ CTE, ๋ณด์•ˆ ๊ฒ€์ฆ ํฌํ•จ **โš ๏ธ ์ฃผ์˜**: ๋™์  ์ฟผ๋ฆฌ๋Š” SQL ์ธ์ ์…˜ ๋ฐฉ์ง€๊ฐ€ ๋งค์šฐ ์ค‘์š”! - diff --git a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md index fd04cb18..2f74db2b 100644 --- a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md +++ b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md @@ -144,11 +144,11 @@ backend-node/ (๋ฃจํŠธ) - `batchExecutionLogService.ts` (7๊ฐœ) - ๋ฐฐ์น˜ ์‹คํ–‰ ๋กœ๊ทธ - `batchManagementService.ts` (5๊ฐœ) - ๋ฐฐ์น˜ ๊ด€๋ฆฌ - `batchSchedulerService.ts` (4๊ฐœ) - ๋ฐฐ์น˜ ์Šค์ผ€์ค„๋Ÿฌ -- **๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ์„œ๋น„์Šค (18๊ฐœ)** - [ํ†ตํ•ฉ ๊ณ„ํš์„œ](PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md) - - `enhancedDynamicFormService.ts` (6๊ฐœ) - ํ™•์žฅ ๋™์  ํผ - - `dataMappingService.ts` (5๊ฐœ) - ๋ฐ์ดํ„ฐ ๋งคํ•‘ - - `dataService.ts` (4๊ฐœ) - ๋ฐ์ดํ„ฐ ์„œ๋น„์Šค - - `adminService.ts` (3๊ฐœ) - ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด +- **๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ์„œ๋น„์Šค (0๊ฐœ)** - โœ… **์ „ํ™˜ ์™„๋ฃŒ** - [ํ†ตํ•ฉ ๊ณ„ํš์„œ](PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md) + - `enhancedDynamicFormService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** + - `dataMappingService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** + - `dataService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** + - `adminService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** - `ddlExecutionService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** (์ด๋ฏธ ์™„๋ฃŒ๋จ) - [๊ณ„ํš์„œ](PHASE3.18_DDL_EXECUTION_SERVICE_MIGRATION.md) - `referenceCacheService.ts` (0๊ฐœ) - โœ… **์ „ํ™˜ ์™„๋ฃŒ** (์ด๋ฏธ ์™„๋ฃŒ๋จ) - [๊ณ„ํš์„œ](PHASE3.17_REFERENCE_CACHE_SERVICE_MIGRATION.md) diff --git a/backend-node/src/services/adminService.ts b/backend-node/src/services/adminService.ts index ddfd8cbc..807a9c57 100644 --- a/backend-node/src/services/adminService.ts +++ b/backend-node/src/services/adminService.ts @@ -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` + // ๊ธฐ์กด Java์˜ selectAdminMenuList ์ฟผ๋ฆฌ๋ฅผ Raw Query๋กœ ํฌํŒ… + // WITH RECURSIVE ์ฟผ๋ฆฌ ๊ตฌํ˜„ + const menuList = await query(` 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` + // ๊ธฐ์กด Java์˜ selectUserMenuList ์ฟผ๋ฆฌ๋ฅผ Raw Query๋กœ ํฌํŒ… + const menuList = await query(` 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( + `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); diff --git a/backend-node/src/services/dataMappingService.ts b/backend-node/src/services/dataMappingService.ts index af7e9759..f6e4df9d 100644 --- a/backend-node/src/services/dataMappingService.ts +++ b/backend-node/src/services/dataMappingService.ts @@ -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(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 { - await this.prisma.$disconnect(); + // No disconnect needed for raw queries } } diff --git a/backend-node/src/services/dataService.ts b/backend-node/src/services/dataService.ts index f4ef2e1b..2608e8c9 100644 --- a/backend-node/src/services/dataService.ts +++ b/backend-node/src/services/dataService.ts @@ -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(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 { 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 { - const result = await prisma.$queryRawUnsafe( - ` - SELECT column_name, data_type, is_nullable, column_default + const result = await query( + `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 { 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; diff --git a/backend-node/src/services/enhancedDynamicFormService.ts b/backend-node/src/services/enhancedDynamicFormService.ts index 2ffbfdad..d9670db4 100644 --- a/backend-node/src/services/enhancedDynamicFormService.ts +++ b/backend-node/src/services/enhancedDynamicFormService.ts @@ -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 { 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( + `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 { 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(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(updateQuery, updateValues); return { data: result[0],