1#[cfg(feature = "database")]
6use sqlx::{Database, Pool};
7use serde_json::Value;
8use crate::error::Result;
9use crate::generation::DataForge;
10
11pub mod schema;
13pub use schema::{TableSchema, FieldSchema, DataType, SchemaParser};
14
15pub trait DatabaseAdapter {
17 fn infer_schema(&self) -> Result<TableSchema>;
19
20 fn bulk_insert(&self, table: &str, data: Vec<Value>) -> Result<usize>;
22
23 fn type_mapping(&self, rust_type: &str) -> String;
25}
26
27#[cfg(feature = "database")]
29pub struct GenericDatabaseForge<DB: Database> {
30 #[allow(dead_code)]
31 pool: Pool<DB>,
32 tables: Vec<TableConfig>,
33 schema_parser: SchemaParser,
34}
35
36pub struct SimpleDatabaseForge {
38 #[allow(dead_code)]
39 forge: DataForge,
40 connection_string: String,
41 batch_size: usize,
42 schema_parser: SchemaParser,
43}
44
45pub struct TableConfig {
47 pub name: String,
48 pub count: usize,
49 pub fields: Vec<FieldConfig>,
50}
51
52pub struct FieldConfig {
54 pub name: String,
55 pub generator: Box<dyn Fn() -> Value + Send + Sync>,
56}
57
58#[cfg(feature = "database")]
59impl<DB: Database> GenericDatabaseForge<DB> {
60 pub fn new(pool: Pool<DB>) -> Self {
62 Self {
63 pool,
64 tables: Vec::new(),
65 schema_parser: SchemaParser::new(),
66 }
67 }
68
69 pub fn table<F>(mut self, name: &str, count: usize, config: F) -> Self
71 where
72 F: FnOnce(&mut TableBuilder) -> &mut TableBuilder,
73 {
74 let mut builder = TableBuilder::new(name.to_string());
75 config(&mut builder);
76 self.tables.push(builder.build(count));
77 self
78 }
79
80 pub async fn fill(&self) -> Result<()> {
82 for table in &self.tables {
83 self.fill_table(table).await?;
84 }
85 Ok(())
86 }
87
88 async fn fill_table(&self, _table: &TableConfig) -> Result<()> {
90 todo!("Database-specific implementation needed")
92 }
93
94 pub fn schema_parser(&self) -> &SchemaParser {
96 &self.schema_parser
97 }
98
99 pub fn schema_parser_mut(&mut self) -> &mut SchemaParser {
101 &mut self.schema_parser
102 }
103}
104
105impl SimpleDatabaseForge {
106 pub fn new(connection_string: &str) -> Self {
108 Self {
109 forge: DataForge::default(),
110 connection_string: connection_string.to_string(),
111 batch_size: 1000,
112 schema_parser: SchemaParser::new(),
113 }
114 }
115
116 pub fn batch_size(mut self, size: usize) -> Self {
118 self.batch_size = size;
119 self
120 }
121
122 pub fn table<F>(self, table_name: &str, count: usize, config: F) -> TableFillConfig
124 where
125 F: FnOnce(&mut TableBuilder) -> &mut TableBuilder,
126 {
127 let mut builder = TableBuilder::new(table_name.to_string());
128 config(&mut builder);
129
130 TableFillConfig {
131 forge: self,
132 table_name: table_name.to_string(),
133 count,
134 fields: builder.build_simple(),
135 }
136 }
137
138 pub fn schema_parser(&self) -> &SchemaParser {
140 &self.schema_parser
141 }
142
143 pub fn schema_parser_mut(&mut self) -> &mut SchemaParser {
145 &mut self.schema_parser
146 }
147
148 pub fn connection_string(&self) -> &str {
150 &self.connection_string
151 }
152
153 pub fn get_batch_size(&self) -> usize {
155 self.batch_size
156 }
157}
158
159pub struct TableFillConfig {
161 #[allow(dead_code)]
162 forge: SimpleDatabaseForge,
163 table_name: String,
164 count: usize,
165 fields: Vec<(String, Box<dyn Fn() -> Value + Send + Sync>)>,
166}
167
168impl TableFillConfig {
169 #[cfg(feature = "database")]
171 pub async fn fill(self) -> Result<usize> {
172 println!("模拟填充表 {} 共 {} 条记录", self.table_name, self.count);
175
176 for i in 0..self.count.min(5) { let mut record = serde_json::Map::new();
179 for (field_name, generator) in &self.fields {
180 record.insert(field_name.clone(), generator());
181 }
182 println!("记录 {}: {}", i + 1, serde_json::to_string_pretty(&record)?);
183 }
184
185 Ok(self.count)
186 }
187
188 pub fn fill_sync(self) -> Result<usize> {
190 println!("填充表 {} 共 {} 条记录", self.table_name, self.count);
191
192 for i in 0..self.count.min(5) { let mut record = serde_json::Map::new();
195 for (field_name, generator) in &self.fields {
196 record.insert(field_name.clone(), generator());
197 }
198 println!("记录 {}: {}", i + 1, serde_json::to_string_pretty(&record)?);
199 }
200
201 Ok(self.count)
202 }
203
204 pub fn table_name(&self) -> &str {
206 &self.table_name
207 }
208
209 pub fn count(&self) -> usize {
211 self.count
212 }
213
214 pub fn fields(&self) -> &Vec<(String, Box<dyn Fn() -> Value + Send + Sync>)> {
216 &self.fields
217 }
218}
219
220pub struct TableBuilder {
222 name: String,
223 fields: Vec<FieldConfig>,
224}
225
226impl TableBuilder {
227 fn new(name: String) -> Self {
228 Self {
229 name,
230 fields: Vec::new(),
231 }
232 }
233
234 pub fn field<F>(&mut self, name: &str, generator: F) -> &mut Self
236 where
237 F: Fn() -> Value + Send + Sync + 'static,
238 {
239 self.fields.push(FieldConfig {
240 name: name.to_string(),
241 generator: Box::new(generator),
242 });
243 self
244 }
245
246 fn build(self, count: usize) -> TableConfig {
248 TableConfig {
249 name: self.name,
250 count,
251 fields: self.fields,
252 }
253 }
254
255 fn build_simple(self) -> Vec<(String, Box<dyn Fn() -> Value + Send + Sync>)> {
257 self.fields.into_iter().map(|field| (field.name, field.generator)).collect()
258 }
259}
260
261pub type DatabaseForge = SimpleDatabaseForge;
264
265#[cfg(feature = "database")]
267pub type MySqlForge = GenericDatabaseForge<sqlx::MySql>;
268
269#[cfg(feature = "database")]
271pub type PostgresForge = GenericDatabaseForge<sqlx::Postgres>;
272
273#[cfg(feature = "database")]
275pub type SqliteForge = GenericDatabaseForge<sqlx::Sqlite>;
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn test_simple_database_forge() {
283 let forge = SimpleDatabaseForge::new("sqlite://test.db");
284 assert_eq!(forge.connection_string, "sqlite://test.db");
285 assert_eq!(forge.batch_size, 1000);
286 }
287
288 #[test]
289 fn test_table_builder() {
290 let mut builder = TableBuilder::new("users".to_string());
291 builder
292 .field("id", || Value::String("test".to_string()))
293 .field("name", || Value::String("test_name".to_string()));
294
295 let table = builder.build(100);
296 assert_eq!(table.name, "users");
297 assert_eq!(table.count, 100);
298 assert_eq!(table.fields.len(), 2);
299 }
300
301 #[test]
302 fn test_schema_parser_integration() {
303 let forge = SimpleDatabaseForge::new("test://db");
304 let parser = forge.schema_parser();
305
306 let json_schema = serde_json::json!({
309 "title": "Test",
310 "properties": {
311 "id": {"type": "integer"}
312 }
313 });
314
315 let result = parser.infer_from_json(&json_schema);
316 assert!(result.is_ok());
317 }
318}