const mysql = require('mysql2/promise'); const path = require('path'); const fs = require('fs'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); const dbConfig = { host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, multipleStatements: true }; function outputProgress(data) { console.log(JSON.stringify(data)); } function getMetricsTablesFromSchema() { const schemaPath = path.join(__dirname, '../db/metrics-schema.sql'); const schemaSQL = fs.readFileSync(schemaPath, 'utf8'); // Extract table names from CREATE TABLE statements const createTableRegex = /CREATE TABLE.*?`(\w+)`/g; const tables = []; let match; while ((match = createTableRegex.exec(schemaSQL)) !== null) { tables.push(match[1]); } return tables; } async function checkIndexExists(connection, tableName, indexName) { const [rows] = await connection.query(` SELECT COUNT(*) as count FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?`, [tableName, indexName] ); return rows[0].count > 0; } async function createMetricsIndexes(connection) { // Check and create orders index const ordersIndexExists = await checkIndexExists(connection, 'orders', 'idx_orders_metrics'); if (!ordersIndexExists) { await connection.query('CREATE INDEX idx_orders_metrics ON orders (product_id, date, canceled, quantity, price)'); } // Check and create purchase_orders index const poIndexExists = await checkIndexExists(connection, 'purchase_orders', 'idx_purchase_orders_metrics'); if (!poIndexExists) { await connection.query('CREATE INDEX idx_purchase_orders_metrics ON purchase_orders (product_id, date, status, ordered, received)'); } } async function resetMetrics() { outputProgress({ status: 'running', operation: 'Starting metrics reset', percentage: '0' }); const connection = await mysql.createConnection(dbConfig); try { // Get list of metrics tables from schema const metricsTables = getMetricsTablesFromSchema(); // Disable foreign key checks first await connection.query('SET FOREIGN_KEY_CHECKS = 0'); // Get list of existing metrics tables if (metricsTables.length > 0) { const [tables] = await connection.query(` SELECT GROUP_CONCAT(table_name) as tables FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name IN (${metricsTables.map(table => `'${table}'`).join(',')})` ); if (tables[0].tables) { outputProgress({ status: 'running', operation: 'Dropping metrics tables', percentage: '40' }); // Drop all metrics tables in one query const dropQuery = `DROP TABLE IF EXISTS ${tables[0].tables.split(',').map(table => '`' + table + '`').join(', ')}`; await connection.query(dropQuery); } } // Read and execute metrics schema (without the index creation) outputProgress({ status: 'running', operation: 'Creating metrics tables', percentage: '60' }); const schemaPath = path.join(__dirname, '../db/metrics-schema.sql'); let schemaSQL = fs.readFileSync(schemaPath, 'utf8'); // Remove the index creation statements from the schema schemaSQL = schemaSQL.split('-- Create optimized indexes')[0]; await connection.query(schemaSQL); // Create indexes if they don't exist outputProgress({ status: 'running', operation: 'Checking and creating indexes', percentage: '80' }); await createMetricsIndexes(connection); // Re-enable foreign key checks await connection.query('SET FOREIGN_KEY_CHECKS = 1'); outputProgress({ status: 'complete', operation: 'Metrics tables have been reset', percentage: '100' }); return { success: true }; } catch (error) { console.error('Error resetting metrics:', error); outputProgress({ status: 'error', operation: 'Failed to reset metrics', error: error.message }); throw error; } finally { await connection.end(); } } // Export the function if being required as a module if (typeof module !== 'undefined' && module.exports) { module.exports = resetMetrics; } // Run directly if called from command line if (require.main === module) { resetMetrics().catch(error => { console.error('Error:', error); process.exit(1); }); }