UNPKG

cyber-mysql-openai

Version:

Intelligent natural language to SQL translator with self-correction capabilities using OpenAI and MySQL

176 lines 6.65 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DBManager = void 0; // src/db/index.ts const promise_1 = __importDefault(require("mysql2/promise")); const index_1 = __importDefault(require("../utils/index")); /** * Clase DBManager que maneja la conexión a la base de datos */ class DBManager { constructor(config, logger) { this.pool = null; this.config = config; this.logger = logger || new index_1.default(); } /** * Obtiene o crea el pool de conexiones */ async getPool() { if (!this.pool) { this.logger.debug("Creating new database connection pool"); try { this.pool = promise_1.default.createPool({ host: this.config.host, port: this.config.port, user: this.config.user, password: this.config.password, database: this.config.database, ssl: this.config.ssl ? { rejectUnauthorized: true } : undefined, socketPath: this.config.socketPath, waitForConnections: true, connectionLimit: 10, queueLimit: 0, }); // Probar la conexión const connection = await this.pool.getConnection(); connection.release(); this.logger.info("Database connection established successfully"); } catch (error) { this.logger.error("Error creating database connection pool:", error); throw new Error(`Failed to connect to database: ${error.message}`); } } return this.pool; } /** * Cierra la conexión al pool */ async closePool() { if (this.pool) { try { await this.pool.end(); this.pool = null; this.logger.info("Database connection pool closed"); } catch (error) { this.logger.error("Error closing database connection pool:", error); throw error; } } } /** * Ejecuta una consulta SQL * @param sql - Consulta SQL * @param params - Parámetros para la consulta * @returns Resultado de la consulta */ async executeQuery(sql, params = []) { try { const pool = await this.getPool(); const [rows] = await pool.query(sql, params); return rows; } catch (error) { this.logger.error("Error executing SQL query:", error); throw error; } } /** * Ejecuta una consulta SQL de solo lectura, validando primero * @param sql - Consulta SQL * @returns Resultado de la consulta */ async executeReadOnlyQuery(sql) { try { // Validar que sea consulta de solo lectura const sqlLowerCase = sql.toLowerCase().trim(); // Verificar si es una consulta de lectura if (!sqlLowerCase.startsWith("select") && !sqlLowerCase.startsWith("show") && !sqlLowerCase.startsWith("describe") && !sqlLowerCase.startsWith("desc") && !sqlLowerCase.startsWith("explain")) { throw new Error("Only SELECT, SHOW, DESCRIBE, and EXPLAIN queries are allowed in read-only mode"); } // Ejecutar la consulta const result = await this.executeQuery(sql); return result; } catch (error) { this.logger.error("Error executing read-only query:", error); throw error; } } /** * Obtiene el esquema de la base de datos incluyendo relaciones * @returns Esquema con columnas y foreign keys por tabla */ async getDatabaseSchema() { try { // Obtener todas las tablas const tables = await this.executeQuery("SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()"); // Obtener todas las FK de una sola vez (más eficiente que por tabla) const foreignKeys = await this.getForeignKeys(); // Resultado para almacenar el esquema const schema = {}; // Para cada tabla, obtener sus columnas for (const table of tables) { const tableName = table.table_name || table.TABLE_NAME; const columns = await this.executeQuery("SELECT column_name, data_type, column_key, is_nullable FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ?", [tableName]); schema[tableName] = { columns, foreignKeys: foreignKeys.filter((fk) => fk.table_name === tableName), }; } return schema; } catch (error) { this.logger.error("Error fetching database schema:", error); throw error; } } /** * Obtiene todas las relaciones Foreign Key de la base de datos * @returns Lista de relaciones FK */ async getForeignKeys() { try { const fks = await this.executeQuery(`SELECT TABLE_NAME as table_name, COLUMN_NAME as column_name, REFERENCED_TABLE_NAME as referenced_table, REFERENCED_COLUMN_NAME as referenced_column FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL`); return fks; } catch (error) { this.logger.warn("Could not fetch foreign keys (non-critical):", error); return []; } } /** * Obtiene las columnas de una tabla específica * @param tableName - Nombre de la tabla * @returns Columnas de la tabla */ async getTableColumns(tableName) { try { const columns = await this.executeQuery("SELECT column_name, data_type, column_key, is_nullable FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ?", [tableName]); return columns; } catch (error) { this.logger.error(`Error fetching columns for table ${tableName}:`, error); throw error; } } } exports.DBManager = DBManager; exports.default = DBManager; //# sourceMappingURL=index.js.map