Skip to main content

dm_database_sqllog2db/pipeline/
normalize_config.rs

1use serde::Deserialize;
2
3/// `[replace_parameters]` 配置段
4#[derive(Debug, Deserialize, Clone)]
5pub struct NormalizeConfig {
6    /// 是否在导出结果中写入 `normalized_sql` 列(默认 true)
7    #[serde(default = "default_true")]
8    pub enable: bool,
9    /// 显式声明 SQL 中使用的占位符列表,例如 `["?"]` 或 `[":1"]`。
10    /// - 只含 `"?"` → 仅匹配 `?` 顺序占位符
11    /// - 含任意 `:N` 形式(如 `":1"`)→ 仅匹配 `:N` 序号占位符
12    /// - 空数组(默认)→ 自动检测
13    #[serde(default)]
14    pub placeholders: Vec<String>,
15}
16
17impl Default for NormalizeConfig {
18    fn default() -> Self {
19        Self {
20            enable: true,
21            placeholders: Vec::new(),
22        }
23    }
24}
25
26impl NormalizeConfig {
27    /// 将 `placeholders` 列表转换为 `compute_normalized` 所需的 `placeholder_override`:
28    /// - `None`        → 自动检测
29    /// - `Some(false)` → 强制 `?` 风格
30    /// - `Some(true)`  → 强制 `:N` 风格
31    #[must_use]
32    pub fn placeholder_override(&self) -> Option<bool> {
33        let has_question = self.placeholders.iter().any(|p| p == "?");
34        let has_colon = self.placeholders.iter().any(|p| {
35            p.starts_with(':') && p[1..].chars().next().is_some_and(|c| c.is_ascii_digit())
36        });
37        match (has_question, has_colon) {
38            (true, false) => Some(false),
39            (false, true) => Some(true),
40            _ => None,
41        }
42    }
43}
44
45fn default_true() -> bool {
46    true
47}