From 4fb92470ce6b302f17680bbaba9b035e2a342f62 Mon Sep 17 00:00:00 2001 From: eshmeshek Date: Wed, 28 Jan 2026 00:00:15 +0300 Subject: [PATCH] modified: backend/src/controllers/databaseManagementController.ts modified: backend/src/controllers/schemaController.ts modified: frontend/src/pages/DatabaseSchema.tsx --- .../databaseManagementController.ts | 8 +++++ backend/src/controllers/schemaController.ts | 29 +++++++++++++++++++ frontend/src/pages/DatabaseSchema.tsx | 13 ++------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/backend/src/controllers/databaseManagementController.ts b/backend/src/controllers/databaseManagementController.ts index f2fe2f5..ab4a844 100644 --- a/backend/src/controllers/databaseManagementController.ts +++ b/backend/src/controllers/databaseManagementController.ts @@ -2,6 +2,7 @@ import { Response } from 'express'; import { AuthRequest } from '../middleware/auth'; import { mainPool } from '../config/database'; import { databasePoolManager } from '../services/DatabasePoolManager'; +import { generateSchemaForDatabase } from './schemaController'; // Только админы могут управлять базами данных export const getDatabases = async (req: AuthRequest, res: Response) => { @@ -92,6 +93,13 @@ export const createDatabase = async (req: AuthRequest, res: Response) => { // Добавить пул подключений (только для не-AQL баз) if (dbType !== 'aql') { await databasePoolManager.reloadPool(newDb.id); + + // Generate schema in background for PostgreSQL databases + if (dbType === 'postgresql') { + generateSchemaForDatabase(newDb.id).catch(err => { + console.error('Background schema generation failed:', err.message); + }); + } } // Не возвращаем пароль diff --git a/backend/src/controllers/schemaController.ts b/backend/src/controllers/schemaController.ts index 4749b0d..96d1a77 100644 --- a/backend/src/controllers/schemaController.ts +++ b/backend/src/controllers/schemaController.ts @@ -33,11 +33,17 @@ interface SchemaData { // Parse PostgreSQL schema async function parsePostgresSchema(databaseId: string): Promise { + const startTime = Date.now(); + console.log(`[Schema] Starting schema parse for database ${databaseId}`); + const pool = databasePoolManager.getPool(databaseId); if (!pool) { throw new Error('Database not found or not active'); } + console.log(`[Schema] Fetching tables list...`); + const tablesStartTime = Date.now(); + // Get all tables with comments via pg_catalog const tablesResult = await pool.query(` SELECT @@ -52,9 +58,17 @@ async function parsePostgresSchema(databaseId: string): Promise { ORDER BY t.table_schema, t.table_name `); + console.log(`[Schema] Found ${tablesResult.rows.length} tables in ${Date.now() - tablesStartTime}ms`); + const tables: TableInfo[] = []; + let processedCount = 0; for (const table of tablesResult.rows) { + processedCount++; + if (processedCount % 50 === 0 || processedCount === tablesResult.rows.length) { + console.log(`[Schema] Processing table ${processedCount}/${tablesResult.rows.length}: ${table.table_schema}.${table.table_name}`); + } + // Get columns for each table const columnsResult = await pool.query(` SELECT @@ -121,6 +135,9 @@ async function parsePostgresSchema(databaseId: string): Promise { }); } + const totalTime = Date.now() - startTime; + console.log(`[Schema] Completed! ${tables.length} tables, ${tables.reduce((acc, t) => acc + t.columns.length, 0)} columns, ${tables.reduce((acc, t) => acc + t.foreign_keys.length, 0)} FKs in ${totalTime}ms`); + return { tables, updated_at: new Date().toISOString(), @@ -188,3 +205,15 @@ export const refreshSchema = async (req: Request, res: Response) => { res.status(500).json({ success: false, error: error.message }); } }; + +// Generate schema for a database (called from other controllers) +export const generateSchemaForDatabase = async (databaseId: string): Promise => { + try { + const schema = await parsePostgresSchema(databaseId); + await saveSchemaToCache(databaseId, schema); + console.log(`Schema generated for database ${databaseId}`); + } catch (error: any) { + console.error(`Error generating schema for database ${databaseId}:`, error.message); + // Don't throw - schema generation is not critical + } +}; diff --git a/frontend/src/pages/DatabaseSchema.tsx b/frontend/src/pages/DatabaseSchema.tsx index 15f842d..aa962df 100644 --- a/frontend/src/pages/DatabaseSchema.tsx +++ b/frontend/src/pages/DatabaseSchema.tsx @@ -14,7 +14,7 @@ import { } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import Dagre from '@dagrejs/dagre'; -import { Database as DatabaseIcon, RefreshCw, Loader2, Key, Link } from 'lucide-react'; +import { Database as DatabaseIcon, Loader2, Key, Link, RefreshCw } from 'lucide-react'; import { databasesApi, schemaApi, TableInfo, SchemaData } from '@/services/api'; import { Database } from '@/types'; @@ -40,7 +40,7 @@ function TableNode({ data }: { data: TableInfo & Record }) { {data.columns.map((col) => (
@@ -54,15 +54,6 @@ function TableNode({ data }: { data: TableInfo & Record }) { {col.type} {!col.nullable && NN} - - {/* Tooltip for column comment */} - {col.comment && ( -
-
- {col.comment} -
-
- )}
))} {data.columns.length === 0 && (