sql_cli/sql/generators/
mod.rs

1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataValue};
2use anyhow::Result;
3use std::sync::Arc;
4
5pub mod math_generators;
6pub mod prime_generators;
7pub mod random_generators;
8pub mod sequence_generators;
9pub mod string_generators;
10
11/// Trait for table-generating functions that produce rows dynamically
12pub trait TableGenerator: Send + Sync {
13    /// Get the name of the generator function (e.g., "GENERATE_PRIMES")
14    fn name(&self) -> &str;
15
16    /// Get the column definitions for the generated table
17    fn columns(&self) -> Vec<DataColumn>;
18
19    /// Generate the table based on the provided arguments
20    /// Arguments are evaluated expressions from the SQL query
21    fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>>;
22
23    /// Get a description of what this generator does
24    fn description(&self) -> &str;
25
26    /// Get the expected number of arguments
27    fn arg_count(&self) -> usize;
28}
29
30/// Registry for table generator functions
31pub struct GeneratorRegistry {
32    generators: std::collections::HashMap<String, Box<dyn TableGenerator>>,
33}
34
35impl GeneratorRegistry {
36    pub fn new() -> Self {
37        let mut registry = Self {
38            generators: std::collections::HashMap::new(),
39        };
40        registry.register_default_generators();
41        registry
42    }
43
44    fn register_default_generators(&mut self) {
45        use math_generators::{Collatz, Factorials, PascalTriangle, Squares, TriangularNumbers};
46        use prime_generators::{Fibonacci, GeneratePrimes, PrimeFactors};
47        use random_generators::{GenerateUUIDs, RandomFloats, RandomIntegers};
48        use sequence_generators::{Dates, Range, Series};
49        use string_generators::{Chars, Lines, Split, Tokenize};
50
51        // Sequence generators
52        self.register(Box::new(Range));
53        self.register(Box::new(Series));
54        self.register(Box::new(Dates));
55
56        // String generators
57        self.register(Box::new(Split));
58        self.register(Box::new(Tokenize));
59        self.register(Box::new(Chars));
60        self.register(Box::new(Lines));
61
62        // Prime and number theory generators
63        self.register(Box::new(GeneratePrimes));
64        self.register(Box::new(PrimeFactors));
65        self.register(Box::new(Fibonacci));
66
67        // Mathematical sequence generators
68        self.register(Box::new(Collatz));
69        self.register(Box::new(PascalTriangle));
70        self.register(Box::new(TriangularNumbers));
71        self.register(Box::new(Squares));
72        self.register(Box::new(Factorials));
73
74        // Random generators
75        self.register(Box::new(RandomIntegers));
76        self.register(Box::new(RandomFloats));
77        self.register(Box::new(GenerateUUIDs));
78    }
79
80    pub fn register(&mut self, generator: Box<dyn TableGenerator>) {
81        self.generators
82            .insert(generator.name().to_uppercase(), generator);
83    }
84
85    pub fn get(&self, name: &str) -> Option<&Box<dyn TableGenerator>> {
86        self.generators.get(&name.to_uppercase())
87    }
88
89    pub fn list(&self) -> Vec<&str> {
90        let mut names: Vec<&str> = self.generators.keys().map(|s| s.as_str()).collect();
91        names.sort();
92        names
93    }
94
95    pub fn list_generators_formatted(&self) -> String {
96        let mut output = String::new();
97        output.push_str("=== Available Generator Functions ===\n\n");
98
99        // Group generators by category
100        let mut sequence_gens = Vec::new();
101        let mut string_gens = Vec::new();
102        let mut math_gens = Vec::new();
103        let mut random_gens = Vec::new();
104        let mut utility_gens = Vec::new();
105
106        for (name, gen) in &self.generators {
107            let entry = format!("  {} - {}", name, gen.description());
108
109            if name == "RANGE" || name == "SERIES" || name == "DATES" {
110                sequence_gens.push(entry);
111            } else if name == "SPLIT" || name == "TOKENIZE" || name == "CHARS" || name == "LINES" {
112                string_gens.push(entry);
113            } else if name.starts_with("RANDOM_") {
114                random_gens.push(entry);
115            } else if name == "GENERATE_UUID" {
116                utility_gens.push(entry);
117            } else {
118                math_gens.push(entry);
119            }
120        }
121
122        if !sequence_gens.is_empty() {
123            sequence_gens.sort();
124            output.push_str("Sequence Generators:\n");
125            for entry in sequence_gens {
126                output.push_str(&format!("{}\n", entry));
127            }
128            output.push('\n');
129        }
130
131        if !string_gens.is_empty() {
132            string_gens.sort();
133            output.push_str("String Generators:\n");
134            for entry in string_gens {
135                output.push_str(&format!("{}\n", entry));
136            }
137            output.push('\n');
138        }
139
140        if !math_gens.is_empty() {
141            math_gens.sort();
142            output.push_str("Mathematical Generators:\n");
143            for entry in math_gens {
144                output.push_str(&format!("{}\n", entry));
145            }
146            output.push('\n');
147        }
148
149        if !random_gens.is_empty() {
150            random_gens.sort();
151            output.push_str("Random Generators:\n");
152            for entry in random_gens {
153                output.push_str(&format!("{}\n", entry));
154            }
155            output.push('\n');
156        }
157
158        if !utility_gens.is_empty() {
159            utility_gens.sort();
160            output.push_str("Utility Generators:\n");
161            for entry in utility_gens {
162                output.push_str(&format!("{}\n", entry));
163            }
164            output.push('\n');
165        }
166
167        output.push_str("Use: SELECT * FROM <generator>(<args>)\n");
168        output.push_str("Example: SELECT * FROM GENERATE_PRIMES(100)\n");
169        output
170    }
171
172    pub fn get_generator_help(&self, name: &str) -> Option<String> {
173        self.generators.get(&name.to_uppercase()).map(|gen| {
174            let mut help = String::new();
175            help.push_str(&format!("=== {} ===\n\n", name.to_uppercase()));
176            help.push_str(&format!("Description: {}\n", gen.description()));
177            help.push_str(&format!(
178                "Arguments: {} argument(s) expected\n",
179                gen.arg_count()
180            ));
181            help.push_str("\nColumns:\n");
182            for col in gen.columns() {
183                help.push_str(&format!("  - {}\n", col.name));
184            }
185            help.push_str("\nExample:\n");
186            help.push_str(&format!("  SELECT * FROM {}(", name.to_uppercase()));
187
188            // Add example arguments based on the generator
189            match name.to_uppercase().as_str() {
190                "GENERATE_PRIMES" => help.push_str("100"),
191                "FIBONACCI" => help.push_str("20"),
192                "PRIME_FACTORS" => help.push_str("1260"),
193                "COLLATZ" => help.push_str("7"),
194                "PASCAL_TRIANGLE" => help.push_str("5"),
195                "TRIANGULAR" | "SQUARES" | "FACTORIALS" => help.push_str("10"),
196                "RANDOM_INT" => help.push_str("10, 1, 100, 42"),
197                "RANDOM_FLOAT" => help.push_str("10, 0, 1, 42"),
198                "GENERATE_UUID" => help.push_str("5"),
199                _ => help.push_str("..."),
200            }
201            help.push_str(");\n");
202            help
203        })
204    }
205}
206
207/// Helper function to create a single-column table
208pub fn create_single_column_table(
209    name: &str,
210    column_name: &str,
211    values: Vec<DataValue>,
212) -> Arc<DataTable> {
213    let mut table = DataTable::new(name);
214    table.add_column(DataColumn::new(column_name));
215
216    for value in values {
217        table.add_row(DataRow::new(vec![value])).unwrap();
218    }
219
220    Arc::new(table)
221}
222
223/// Helper function to create a two-column table
224pub fn create_two_column_table(
225    name: &str,
226    col1_name: &str,
227    col2_name: &str,
228    rows: Vec<(DataValue, DataValue)>,
229) -> Arc<DataTable> {
230    let mut table = DataTable::new(name);
231    table.add_column(DataColumn::new(col1_name));
232    table.add_column(DataColumn::new(col2_name));
233
234    for (val1, val2) in rows {
235        table.add_row(DataRow::new(vec![val1, val2])).unwrap();
236    }
237
238    Arc::new(table)
239}