Skip to main content

sz_orm_graph/
error.rs

1//! # GraphError — 图数据库错误类型
2//!
3//! 6 变体,DSN 脱敏。
4
5use thiserror::Error;
6
7/// 图数据库错误
8#[derive(Debug, Clone, Error)]
9pub enum GraphError {
10    /// 连接错误(DSN 脱敏)
11    #[error("connection error: {0}")]
12    ConnectionError(String),
13
14    /// 查询错误
15    #[error("query error: {0}")]
16    QueryError(String),
17
18    /// 结果映射错误
19    #[error("mapping error: {0}")]
20    MappingError(String),
21
22    /// SQL 不支持(图接口拒绝 SQL 透传)
23    #[error("SQL is not supported in graph interface: {0}")]
24    SqlNotSupported(String),
25
26    /// 参数化错误(检测到字面量拼接)
27    #[error("parameterization error: {0}")]
28    ParameterizationError(String),
29
30    /// 驱动错误
31    #[error("driver error: {0}")]
32    DriverError(String),
33}
34
35/// DSN 脱敏:将密码部分替换为 ***
36pub fn sanitize_dsn(dsn: &str) -> String {
37    if let Some(at_pos) = dsn.find('@') {
38        if let Some(scheme_end) = dsn.find("://") {
39            let auth_part = &dsn[scheme_end + 3..at_pos];
40            if let Some(colon_pos) = auth_part.find(':') {
41                let user = &auth_part[..colon_pos];
42                let rest = &dsn[at_pos..];
43                let scheme = &dsn[..scheme_end + 3];
44                return format!("{}{}:***{}", scheme, user, rest);
45            }
46        }
47    }
48    dsn.to_string()
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_sanitize_dsn_with_password() {
57        let dsn = "neo4j://neo4j:test123@127.0.0.1:7687";
58        let sanitized = sanitize_dsn(dsn);
59        assert!(!sanitized.contains("test123"));
60        assert!(sanitized.contains("***"));
61        assert!(sanitized.contains("neo4j://neo4j:***@127.0.0.1:7687"));
62    }
63
64    #[test]
65    fn test_sanitize_dsn_without_password() {
66        let dsn = "neo4j://127.0.0.1:7687";
67        let sanitized = sanitize_dsn(dsn);
68        assert_eq!(sanitized, dsn);
69    }
70
71    #[test]
72    fn test_graph_error_display() {
73        let e = GraphError::SqlNotSupported("SELECT * FROM users".into());
74        assert!(e.to_string().contains("SQL is not supported"));
75    }
76}