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