dm_database_sqllog2db/
parser.rs

1/// SQL 日志解析模块
2/// 使用 dm-database-parser-sqllog 库解析达梦数据库的 SQL 日志文件
3use crate::error::{Error, ParserError, Result};
4use log::{debug, info, warn};
5use std::path::{Path, PathBuf};
6
7/// SQL 日志解析器
8pub struct SqllogParser {
9    /// 日志路径(文件或目录)
10    path: PathBuf,
11}
12
13impl SqllogParser {
14    /// 创建新的 SQL 日志解析器
15    pub fn new(path: impl AsRef<Path>) -> Self {
16        Self {
17            path: path.as_ref().to_path_buf(),
18        }
19    }
20
21    /// 获取日志路径
22    pub fn path(&self) -> &Path {
23        &self.path
24    }
25
26    /// 返回所有日志文件的路径列表
27    /// 这样用户可以遍历文件,然后对每个文件使用 iter_sqllogs_from_file
28    pub fn log_files(&self) -> Result<Vec<PathBuf>> {
29        self.scan_log_files()
30    }
31
32    /// 扫描并获取所有需要解析的日志文件
33    fn scan_log_files(&self) -> Result<Vec<PathBuf>> {
34        let path = &self.path;
35
36        if !path.exists() {
37            return Err(Error::Parser(ParserError::PathNotFound {
38                path: path.clone(),
39            }));
40        }
41
42        let mut log_files = Vec::new();
43
44        if path.is_file() {
45            // 单个文件
46            info!("Parsing single log file: {}", path.display());
47            log_files.push(path.clone());
48        } else if path.is_dir() {
49            // 目录:扫描所有 .log 文件
50            info!("Scanning log directory: {}", path.display());
51
52            let entries = std::fs::read_dir(path).map_err(|e| {
53                Error::Parser(ParserError::ReadDirFailed {
54                    path: path.clone(),
55                    reason: e.to_string(),
56                })
57            })?;
58
59            for entry in entries {
60                let entry = entry.map_err(|e| {
61                    Error::Parser(ParserError::ReadDirFailed {
62                        path: path.clone(),
63                        reason: e.to_string(),
64                    })
65                })?;
66
67                let entry_path = entry.path();
68
69                // 只处理 .log 文件
70                if entry_path.is_file() && entry_path.extension().is_some_and(|ext| ext == "log") {
71                    debug!("Found log file: {}", entry_path.display());
72                    log_files.push(entry_path);
73                }
74            }
75
76            if log_files.is_empty() {
77                warn!("No .log files found in directory {}", path.display());
78            } else {
79                info!("Found {} log files", log_files.len());
80            }
81        } else {
82            return Err(Error::Parser(ParserError::InvalidPath {
83                path: path.clone(),
84                reason: "既不是文件也不是目录".to_string(),
85            }));
86        }
87
88        Ok(log_files)
89    }
90}