sql_cli/sql/generators/
mod.rs

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