Skip to main content

dm_database_sqllog2db/pipeline/
field_mask.rs

1/// 导出字段名列表(顺序与 CSV/SQLite 列顺序一致,共 15 个字段)
2pub const FIELD_NAMES: &[&str] = &[
3    "ts",             // 0
4    "ep",             // 1
5    "sess_id",        // 2
6    "thrd_id",        // 3
7    "username",       // 4
8    "trx_id",         // 5
9    "statement",      // 6
10    "appname",        // 7
11    "client_ip",      // 8
12    "tag",            // 9
13    "sql",            // 10
14    "exec_time_ms",   // 11
15    "row_count",      // 12
16    "exec_id",        // 13
17    "normalized_sql", // 14
18];
19
20/// 字段投影掩码:u16 位图,bit i=1 表示导出第 i 个字段(共 15 个)
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct FieldMask(pub u16);
23
24impl FieldMask {
25    /// 全部 15 个字段都导出(默认值)
26    pub const ALL: Self = Self(0x7FFF);
27
28    /// 从字段名列表构建掩码,未知字段名返回错误消息
29    pub fn from_names(names: &[String]) -> std::result::Result<Self, String> {
30        let mut mask = 0u16;
31        for name in names {
32            match FIELD_NAMES.iter().position(|&n| n == name.as_str()) {
33                Some(idx) => mask |= 1u16 << idx,
34                None => return Err(format!("unknown field: '{name}'")),
35            }
36        }
37        Ok(Self(mask))
38    }
39
40    /// 第 `idx` 个字段是否启用
41    #[inline]
42    #[must_use]
43    pub(crate) fn is_active(self, idx: usize) -> bool {
44        idx < 15 && (self.0 >> idx) & 1 == 1
45    }
46
47    /// `normalized_sql` 字段(索引 14)是否启用
48    #[inline]
49    #[must_use]
50    pub fn includes_normalized_sql(self) -> bool {
51        self.is_active(14)
52    }
53}
54
55impl Default for FieldMask {
56    fn default() -> Self {
57        Self::ALL
58    }
59}