dataforge/filling/
utils.rs

1//! 通用工具函数模块
2
3use librarys::random_letters;
4use serde_json::Value;
5use crate::generators::{number, datetime, internet};
6
7/// 根据表结构生成数据
8pub fn generate_sample_data_by_schema(schema: &crate::db::schema::TableSchema, _id: usize) -> Value {
9    use crate::generation::DataForge;
10    use crate::db::schema::DataType;
11    // use rand::seq::SliceRandom;
12    
13    let mut data = serde_json::Map::new();
14    
15    // 使用 data-forge 的核心生成能力
16    let forge = DataForge::new(crate::generation::Language::ZhCN);
17    
18    // 根据表结构动态生成数据,完全基于字段类型而不是字段名称
19    for field in &schema.fields {
20        let value = match &field.data_type {
21            // 字符串类型字段 - 完全基于字段类型生成,不依赖字段名称
22            DataType::String { max_length } => {
23                let max_len = max_length.unwrap_or(255) as usize;
24                // 使用 data-forge 的随机字符串生成能力
25                Value::String(random_letters(std::cmp::min(10, max_len)))
26            },
27            // 整数类型字段 - 完全基于字段类型生成,不依赖字段名称
28            DataType::Integer { .. } => {
29                // 使用 data-forge 的数字生成能力
30                forge.generate("random_int").unwrap_or_else(|| {
31                    Value::Number(serde_json::Number::from(number::random_int(0, 1000000)))
32                })
33            },
34            // 浮点数类型字段 - 完全基于字段类型生成,不依赖字段名称
35            DataType::Float { .. } => {
36                // 使用 data-forge 的浮点数生成能力
37                forge.generate("random_float").unwrap_or_else(|| {
38                    Value::Number(serde_json::Number::from_f64(number::random_float(0.0, 1000.0)).unwrap())
39                })
40            },
41            // 布尔类型字段 - 完全基于字段类型生成,不依赖字段名称
42            DataType::Boolean => { 
43                // 使用 data-forge 的布尔值生成能力
44                forge.generate("random_bool").unwrap_or_else(|| {
45                    Value::Bool(rand::random())
46                })
47            },
48            // 日期时间类型字段 - 完全基于字段类型生成,不依赖字段名称
49            DataType::DateTime { .. } => {
50                // 使用 data-forge 的日期时间生成能力
51                forge.generate("datetime_now").unwrap_or_else(|| {
52                    Value::String(datetime::iso8601())
53                })
54            },
55            // 日期类型字段 - 完全基于字段类型生成,不依赖字段名称
56            DataType::Date { .. } => {
57                // 使用 data-forge 的日期生成能力
58                forge.generate("date_now").unwrap_or_else(|| {
59                    Value::String(datetime::date_iso())
60                })
61            },
62            // 邮箱类型字段 - 完全基于字段类型生成,不依赖字段名称
63            DataType::Email => {
64                // 使用 data-forge 的邮箱生成能力
65                forge.generate("email").unwrap_or_else(|| {
66                    Value::String(internet::email())
67                })
68            },
69            // 电话类型字段 - 完全基于字段类型生成,不依赖字段名称
70            DataType::Phone { .. } => {
71                // 使用 data-forge 的电话号码生成能力
72                forge.generate("phone_cn").unwrap_or_else(|| {
73                    Value::String(number::phone_number_cn())
74                })
75            },
76            // UUID类型字段 - 完全基于字段类型生成,不依赖字段名称
77            DataType::Uuid => {
78                // 使用 data-forge 的UUID生成能力
79                forge.generate("uuid_v4").unwrap_or_else(|| {
80                    Value::String(crate::generators::uuid_v4())
81                })
82            },
83            // URL类型字段 - 完全基于字段类型生成,不依赖字段名称
84            DataType::Url => {
85                // 使用 data-forge 的URL生成能力
86                forge.generate("url").unwrap_or_else(|| {
87                    Value::String(crate::generators::internet::url())
88                })
89            },
90            // 其他类型字段
91            _ => {
92                // 默认生成字符串值
93                Value::String(random_letters(10))
94            }
95        };
96        data.insert(field.name.clone(), value);
97    }
98    
99    serde_json::Value::Object(data)
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105    // 在测试模块中导入 forge 宏
106    use crate::forge;
107    use crate::{name, datetime, internet, number};
108
109    /// 生成示例员工数据
110    fn generate_sample_employee_data(id: usize) -> Value {
111        use rand::seq::SliceRandom;
112        let mut rng = rand::thread_rng();
113        
114        let gender_options = ["M", "F"];
115        let department_options = ["Engineering", "HR", "Finance", "Marketing", "Sales"];
116        let position_options = ["Developer", "Manager", "Analyst", "Designer", "Tester"];
117        
118        forge!({
119            "emp_no" => 100000 + id,
120            "first_name" => name::en_first_name(),
121            "last_name" => name::en_last_name(),
122            "gender" => gender_options.choose(&mut rng).unwrap(),
123            "birth_date" => datetime::random_date_between("1950-01-01", "2000-12-31"),
124            "hire_date" => datetime::random_date_between("2000-01-01", "2023-12-31"),
125            "email" => internet::email(),
126            "phone" => number::phone_number_cn(),
127            "salary" => number::random_int(30000, 200000),
128            "department" => department_options.choose(&mut rng).unwrap(),
129            "position" => position_options.choose(&mut rng).unwrap()
130        })
131    }
132    #[test]
133    fn test_random_string() {
134        let s = random_letters(10);
135        assert_eq!(s.len(), 10);
136        assert!(s.chars().all(|c| c.is_alphanumeric()));
137    }
138
139    #[test]
140    fn test_generate_sample_employee_data() {
141        let employee = generate_sample_employee_data(1);
142        assert!(employee.is_object());
143        assert!(employee.get("emp_no").is_some());
144        assert!(employee.get("first_name").is_some());
145        assert!(employee.get("last_name").is_some());
146        assert!(employee.get("gender").is_some());
147        assert!(employee.get("birth_date").is_some());
148        assert!(employee.get("hire_date").is_some());
149        assert!(employee.get("email").is_some());
150        assert!(employee.get("phone").is_some());
151        assert!(employee.get("salary").is_some());
152        assert!(employee.get("department").is_some());
153        assert!(employee.get("position").is_some());
154    }
155
156    #[test]
157    fn test_generate_sample_employee_data_by_schema() {
158        // 创建一个简单的员工表结构
159        let schema = crate::db::schema::TableSchema {
160            name: "employees".to_string(),
161            fields: vec![
162                crate::db::schema::FieldSchema {
163                    name: "emp_no".to_string(),
164                    data_type: crate::db::schema::DataType::Integer { min: None, max: None },
165                    constraints: crate::db::schema::FieldConstraints {
166                        nullable: false,
167                        unique: true,
168                        default: None,
169                        pattern: None,
170                        min: None,
171                        max: None,
172                    },
173                    description: None,
174                    generator_config: None,
175                    generator_type: None,
176                },
177                crate::db::schema::FieldSchema {
178                    name: "first_name".to_string(),
179                    data_type: crate::db::schema::DataType::String { max_length: Some(50) },
180                    constraints: crate::db::schema::FieldConstraints {
181                        nullable: false,
182                        unique: false,
183                        default: None,
184                        pattern: None,
185                        min: None,
186                        max: None,
187                    },
188                    description: None,
189                    generator_config: None,
190                    generator_type: None,
191                },
192                crate::db::schema::FieldSchema {
193                    name: "last_name".to_string(),
194                    data_type: crate::db::schema::DataType::String { max_length: Some(50) },
195                    constraints: crate::db::schema::FieldConstraints {
196                        nullable: false,
197                        unique: false,
198                        default: None,
199                        pattern: None,
200                        min: None,
201                        max: None,
202                    },
203                    description: None,
204                    generator_config: None,
205                    generator_type: None,
206                },
207            ],
208            primary_key: Some(vec!["emp_no".to_string()]),
209            indexes: vec![],
210            description: None,
211        };
212        
213        let employee = generate_sample_data_by_schema(&schema, 1);
214        assert!(employee.is_object());
215        assert!(employee.get("emp_no").is_some());
216        assert!(employee.get("first_name").is_some());
217        assert!(employee.get("last_name").is_some());
218    }
219}