Skip to main content

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