Skip to main content

sz_orm_core/seeding/
mod.rs

1//! 数据 seeding/fixture 管理模块(v4.1.0,`data-seeding` feature gate)
2//!
3//! 提供 `FakerGenerator`(faker 数据生成)、`FixtureLoader`(fixture 模板加载)、
4//! `SeedManager`(种子版本管理 + 依赖排序 + 幂等执行 + 环境隔离)。
5
6pub mod faker;
7pub mod fixture;
8pub mod manager;
9
10pub use faker::FakerGenerator;
11pub use fixture::{FixtureLoader, FixtureTemplate, Reference};
12pub use manager::{SeedEnv, SeedFile, SeedManager, SeedMode, SeedReport};
13
14use serde_json::Value;
15use thiserror::Error;
16
17/// 字段生成器 trait(扩展性:用户可注册自定义生成器)
18pub trait FieldGenerator: Send + Sync {
19    /// 生成一个字段值
20    fn generate(&self, rng: &mut rand::rngs::StdRng) -> Value;
21}
22
23/// 字段类型(用于推断默认生成器)
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum FieldType {
26    /// 字符串类型
27    String,
28    /// 32 位有符号整数
29    I32,
30    /// 32 位无符号整数
31    U32,
32    /// 64 位有符号整数
33    I64,
34    /// 64 位无符号整数
35    U64,
36    /// 64 位浮点数
37    F64,
38    /// 布尔类型
39    Boolean,
40    /// UUID 类型
41    Uuid,
42    /// 日期时间类型
43    DateTime,
44    /// JSON 类型
45    Json,
46    /// 枚举类型,包含所有可选值
47    Enum(Vec<String>),
48}
49
50/// 模型字段定义
51#[derive(Debug, Clone)]
52pub struct FieldDef {
53    /// 字段名
54    pub name: String,
55    /// 字段类型
56    pub field_type: FieldType,
57    /// 是否可为 NULL
58    pub nullable: bool,
59}
60
61/// 模型定义(用于批量生成)
62#[derive(Debug, Clone)]
63pub struct ModelDef {
64    /// 目标表名
65    pub table: String,
66    /// 字段列表
67    pub fields: Vec<FieldDef>,
68}
69
70/// seeding 错误类型
71#[derive(Debug, Error)]
72pub enum SeedError {
73    /// 生产环境 seeding 被禁止
74    #[error("production seeding forbidden: set allow_production=true to override")]
75    EnvForbidden,
76    /// 检测到依赖循环
77    #[error("dependency cycle detected: {chain}")]
78    DependencyCycle {
79        /// 循环链描述
80        chain: String,
81    },
82    /// fixture 文件解析失败
83    #[error("fixture parse failed at {path}: {reason}")]
84    FixtureParseFailed {
85        /// 文件路径
86        path: String,
87        /// 失败原因
88        reason: String,
89    },
90    /// seed 执行失败
91    #[error("seed execution failed at version {version}: {reason}")]
92    SeedExecution {
93        /// 种子版本
94        version: String,
95        /// 失败原因
96        reason: String,
97    },
98    /// 配置无效
99    #[error("invalid config: {0}")]
100    InvalidConfig(String),
101    /// IO 错误
102    #[error("io error: {0}")]
103    Io(#[from] std::io::Error),
104    /// YAML 解析错误
105    #[error("yaml parse error: {0}")]
106    Yaml(#[from] serde_yaml::Error),
107    /// JSON 解析错误
108    #[error("json parse error: {0}")]
109    Json(#[from] serde_json::Error),
110}
111
112/// 生成的记录(字段名 → 值)
113pub type Record = serde_json::Map<String, Value>;
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_field_type_equality() {
121        assert_eq!(FieldType::String, FieldType::String);
122        assert_ne!(FieldType::I32, FieldType::U32);
123    }
124
125    #[test]
126    fn test_seed_error_display() {
127        let err = SeedError::EnvForbidden;
128        assert!(err.to_string().contains("production seeding forbidden"));
129
130        let err = SeedError::DependencyCycle {
131            chain: "A<-B<-A".to_string(),
132        };
133        assert!(err.to_string().contains("A<-B<-A"));
134    }
135}