sql_cli/sql/generators/
mod.rs

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