sql_cli/sql/generators/
literal_generators.rs1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
2use crate::sql::generators::TableGenerator;
3use anyhow::{anyhow, Result};
4use std::collections::HashMap;
5use std::sync::Arc;
6
7pub struct Values;
11
12impl TableGenerator for Values {
13 fn name(&self) -> &str {
14 "VALUES"
15 }
16
17 fn columns(&self) -> Vec<DataColumn> {
18 vec![DataColumn {
19 name: "value".to_string(),
20 data_type: DataType::Float, nullable: false,
22 unique_values: Some(0),
23 null_count: 0,
24 metadata: HashMap::new(),
25 qualified_name: None,
26 source_table: None,
27 }]
28 }
29
30 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
31 if args.is_empty() {
32 return Err(anyhow!("VALUES expects at least one argument"));
33 }
34
35 let mut table = DataTable::new("values");
36 table.add_column(DataColumn::new("value"));
37
38 for (i, arg) in args.iter().enumerate() {
40 let value = match arg {
41 DataValue::Integer(n) => DataValue::Integer(*n),
42 DataValue::Float(f) => DataValue::Float(*f),
43 DataValue::String(s) => {
44 if let Ok(n) = s.parse::<i64>() {
46 DataValue::Integer(n)
47 } else if let Ok(f) = s.parse::<f64>() {
48 DataValue::Float(f)
49 } else {
50 return Err(anyhow!(
51 "VALUES argument {} ('{}') cannot be converted to a number",
52 i + 1,
53 s
54 ));
55 }
56 }
57 DataValue::Null => DataValue::Null,
58 _ => {
59 return Err(anyhow!(
60 "VALUES expects numeric arguments, got {:?} at position {}",
61 arg,
62 i + 1
63 ))
64 }
65 };
66
67 table
68 .add_row(DataRow::new(vec![value]))
69 .map_err(|e| anyhow!(e))?;
70 }
71
72 Ok(Arc::new(table))
73 }
74
75 fn description(&self) -> &str {
76 "Generate a table from literal values"
77 }
78
79 fn arg_count(&self) -> usize {
80 0 }
82}
83
84pub struct Array;
87
88impl TableGenerator for Array {
89 fn name(&self) -> &str {
90 "ARRAY"
91 }
92
93 fn columns(&self) -> Vec<DataColumn> {
94 vec![
95 DataColumn {
96 name: "index".to_string(),
97 data_type: DataType::Integer,
98 nullable: false,
99 unique_values: Some(0),
100 null_count: 0,
101 metadata: HashMap::new(),
102 qualified_name: None,
103 source_table: None,
104 },
105 DataColumn {
106 name: "value".to_string(),
107 data_type: DataType::Float,
108 nullable: false,
109 unique_values: Some(0),
110 null_count: 0,
111 metadata: HashMap::new(),
112 qualified_name: None,
113 source_table: None,
114 },
115 ]
116 }
117
118 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
119 if args.is_empty() {
120 return Err(anyhow!("ARRAY expects at least one argument"));
121 }
122
123 let mut table = DataTable::new("array");
124 table.add_column(DataColumn::new("index"));
125 table.add_column(DataColumn::new("value"));
126
127 for (i, arg) in args.iter().enumerate() {
129 let value = match arg {
130 DataValue::Integer(n) => DataValue::Integer(*n),
131 DataValue::Float(f) => DataValue::Float(*f),
132 DataValue::String(s) => {
133 if let Ok(n) = s.parse::<i64>() {
135 DataValue::Integer(n)
136 } else if let Ok(f) = s.parse::<f64>() {
137 DataValue::Float(f)
138 } else {
139 return Err(anyhow!(
140 "ARRAY argument {} ('{}') cannot be converted to a number",
141 i + 1,
142 s
143 ));
144 }
145 }
146 DataValue::Null => DataValue::Null,
147 _ => {
148 return Err(anyhow!(
149 "ARRAY expects numeric arguments, got {:?} at position {}",
150 arg,
151 i + 1
152 ))
153 }
154 };
155
156 table
157 .add_row(DataRow::new(vec![DataValue::Integer(i as i64), value]))
158 .map_err(|e| anyhow!(e))?;
159 }
160
161 Ok(Arc::new(table))
162 }
163
164 fn description(&self) -> &str {
165 "Generate a table from an array of literal values with index"
166 }
167
168 fn arg_count(&self) -> usize {
169 0 }
171}