// 检查ClickHouse数据库结构的脚本 const { createClient } = require('@clickhouse/client'); const dotenv = require('dotenv'); const path = require('path'); const fs = require('fs'); // 加载环境变量 dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // 定义输出目录 const DB_REPORTS_DIR = path.resolve(__dirname, '../db-reports'); // 获取ClickHouse配置 const clickhouseHost = process.env.CLICKHOUSE_HOST || 'localhost'; const clickhousePort = process.env.CLICKHOUSE_PORT || '8123'; const clickhouseUser = process.env.CLICKHOUSE_USER || 'default'; const clickhousePassword = process.env.CLICKHOUSE_PASSWORD || ''; const clickhouseDatabase = process.env.CLICKHOUSE_DATABASE || 'default'; console.log('ClickHouse配置:'); console.log(` - 主机: ${clickhouseHost}`); console.log(` - 端口: ${clickhousePort}`); console.log(` - 用户: ${clickhouseUser}`); console.log(` - 数据库: ${clickhouseDatabase}`); // 创建ClickHouse客户端 - 使用0.2.10版本的API const client = createClient({ url: `http://${clickhouseHost}:${clickhousePort}`, username: clickhouseUser, password: clickhousePassword, database: clickhouseDatabase }); // 获取所有表 async function getAllTables() { console.log('\n获取所有表...'); try { const query = ` SELECT name FROM system.tables WHERE database = '${clickhouseDatabase}' `; const resultSet = await client.query({ query, format: 'JSONEachRow' }); const tables = await resultSet.json(); if (!tables || tables.length === 0) { console.log(`数据库 ${clickhouseDatabase} 中没有找到任何表`); return null; } console.log(`数据库 ${clickhouseDatabase} 中找到以下表:`); tables.forEach(table => { console.log(` - ${table.name}`); }); return tables.map(table => table.name); } catch (error) { console.error('获取所有表时出错:', error); return null; } } // 获取表结构 async function getTableSchema(tableName) { console.log(`\n获取表 ${tableName} 的结构...`); try { const query = ` DESCRIBE TABLE ${clickhouseDatabase}.${tableName} `; const resultSet = await client.query({ query, format: 'JSONEachRow' }); const columns = await resultSet.json(); if (!columns || columns.length === 0) { console.log(`表 ${tableName} 不存在或没有列`); return null; } console.log(`表 ${tableName} 的列:`); columns.forEach(column => { console.log(` - ${column.name} (${column.type}, ${column.default_type === '' ? '无默认值' : `默认值: ${column.default_expression}`})`); }); return columns; } catch (error) { console.error(`获取表 ${tableName} 结构时出错:`, error); return null; } } // 获取表数据示例 async function getTableDataSample(tableName, limit = 5) { console.log(`\n获取表 ${tableName} 的数据示例 (最多 ${limit} 行)...`); try { const query = ` SELECT * FROM ${clickhouseDatabase}.${tableName} LIMIT ${limit} `; const resultSet = await client.query({ query, format: 'JSONEachRow' }); const rows = await resultSet.json(); if (!rows || rows.length === 0) { console.log(`表 ${tableName} 中没有数据`); return null; } console.log(`表 ${tableName} 的数据示例:`); rows.forEach((row, index) => { console.log(` 行 ${index + 1}:`); Object.entries(row).forEach(([key, value]) => { console.log(` ${key}: ${value}`); }); }); return rows; } catch (error) { console.error(`获取表 ${tableName} 数据示例时出错:`, error); return null; } } // 主函数 async function main() { let outputBuffer = ''; const originalConsoleLog = console.log; // 重定向console.log到buffer和控制台 console.log = function() { // 调用原始的console.log originalConsoleLog.apply(console, arguments); // 写入到buffer outputBuffer += Array.from(arguments).join(' ') + '\n'; }; try { // 获取所有表 const tables = await getAllTables(); if (!tables) { console.error('无法获取表列表'); process.exit(1); } console.log('\n所有ClickHouse表:'); console.log(tables.join(', ')); // 获取每个表的结构,但不获取数据示例 for (const tableName of tables) { await getTableSchema(tableName); // 移除数据示例检查 // await getTableDataSample(tableName); } console.log('\nClickHouse数据库结构检查完成'); // 保存输出到指定目录 const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); // 确保目录存在 if (!fs.existsSync(DB_REPORTS_DIR)) { fs.mkdirSync(DB_REPORTS_DIR, { recursive: true }); } const outputPath = path.join(DB_REPORTS_DIR, `clickhouse-schema-${timestamp}.log`); fs.writeFileSync(outputPath, outputBuffer); originalConsoleLog(`结果已保存到: ${outputPath}`); } catch (error) { console.error('检查ClickHouse数据库结构时出错:', error); } finally { // 恢复原始的console.log console.log = originalConsoleLog; // 关闭客户端连接 await client.close(); } } // 导出函数 module.exports = { getAllTables, getTableSchema, getTableDataSample, main }; // 如果直接运行此脚本,则执行main函数 if (require.main === module) { main().catch(error => { console.error('运行脚本时出错:', error); process.exit(1); }); }