1use std::collections::BTreeMap;
16use std::fmt::Display;
17use std::fmt::Formatter;
18
19use derive_visitor::Drive;
20use derive_visitor::DriveMut;
21use itertools::Itertools;
22
23use crate::ast::quote::QuotedString;
24use crate::ast::write_comma_separated_list;
25use crate::ast::CreateOption;
26use crate::ast::Expr;
27use crate::ast::Identifier;
28use crate::ast::TypeName;
29
30#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
31pub enum UDFDefinition {
32 LambdaUDF {
33 parameters: Vec<Identifier>,
34 definition: Box<Expr>,
35 },
36 UDFServer {
37 arg_types: Vec<TypeName>,
38 return_type: TypeName,
39 address: String,
40 handler: String,
41 headers: BTreeMap<String, String>,
42 language: String,
43 immutable: Option<bool>,
44 },
45 UDFScript {
46 arg_types: Vec<TypeName>,
47 return_type: TypeName,
48 code: String,
49 imports: Vec<String>,
50 packages: Vec<String>,
51 handler: String,
52 language: String,
53 runtime_version: String,
54 immutable: Option<bool>,
55 },
56 UDAFServer {
57 arg_types: Vec<TypeName>,
58 state_fields: Vec<UDAFStateField>,
59 return_type: TypeName,
60 address: String,
61 headers: BTreeMap<String, String>,
62 language: String,
63 },
64 UDAFScript {
65 arg_types: Vec<TypeName>,
66 state_fields: Vec<UDAFStateField>,
67 return_type: TypeName,
68 imports: Vec<String>,
69 packages: Vec<String>,
70 code: String,
71 language: String,
72 runtime_version: String,
73 },
74}
75
76impl Display for UDFDefinition {
77 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
78 match self {
79 UDFDefinition::LambdaUDF {
80 parameters,
81 definition,
82 } => {
83 write!(f, "AS (")?;
84 write_comma_separated_list(f, parameters)?;
85 write!(f, ") -> {definition}")?;
86 }
87 UDFDefinition::UDFServer {
88 arg_types,
89 return_type,
90 address,
91 handler,
92 headers,
93 language,
94 immutable,
95 } => {
96 write!(f, "( ")?;
97 write_comma_separated_list(f, arg_types)?;
98 write!(f, " ) RETURNS {return_type} LANGUAGE {language}")?;
99 if let Some(immutable) = immutable {
100 if *immutable {
101 write!(f, " IMMUTABLE")?;
102 } else {
103 write!(f, " VOLATILE")?;
104 }
105 }
106 write!(f, " HANDLER = '{handler}'")?;
107 if !headers.is_empty() {
108 write!(f, " HEADERS = (")?;
109 for (i, (key, value)) in headers.iter().enumerate() {
110 if i > 0 {
111 write!(f, ", ")?;
112 }
113 write!(f, "'{key}' = '{value}'")?;
114 }
115 write!(f, ")")?;
116 }
117 write!(f, " ADDRESS = '{address}'")?;
118 }
119 UDFDefinition::UDFScript {
120 arg_types,
121 return_type,
122 code,
123 handler,
124 language,
125 runtime_version: _,
126 imports,
127 packages,
128 immutable,
129 } => {
130 write!(f, "( ")?;
131 write_comma_separated_list(f, arg_types)?;
132 let imports = imports
133 .iter()
134 .map(|s| QuotedString(s, '\'').to_string())
135 .join(",");
136 let packages = packages
137 .iter()
138 .map(|s| QuotedString(s, '\'').to_string())
139 .join(",");
140 write!(f, " ) RETURNS {return_type} LANGUAGE {language}")?;
141 if let Some(immutable) = immutable {
142 if *immutable {
143 write!(f, " IMMUTABLE")?;
144 } else {
145 write!(f, " VOLATILE")?;
146 }
147 }
148 write!(
149 f,
150 " IMPORTS = ({}) PACKAGES = ({}) HANDLER = '{handler}' AS $$\n{code}\n$$",
151 imports, packages
152 )?;
153 }
154 UDFDefinition::UDAFServer {
155 arg_types,
156 state_fields: state_types,
157 return_type,
158 address,
159 headers,
160 language,
161 } => {
162 write!(f, "( ")?;
163 write_comma_separated_list(f, arg_types)?;
164 write!(f, " ) STATE {{ ")?;
165 write_comma_separated_list(f, state_types)?;
166 write!(f, " }} RETURNS {return_type} LANGUAGE {language}")?;
167 if !headers.is_empty() {
168 write!(f, " HEADERS = (")?;
169 for (i, (key, value)) in headers.iter().enumerate() {
170 if i > 0 {
171 write!(f, ", ")?;
172 }
173 write!(f, "'{key}' = '{value}'")?;
174 }
175 write!(f, ")")?;
176 }
177 write!(f, " ADDRESS = '{address}'")?;
178 }
179 UDFDefinition::UDAFScript {
180 arg_types,
181 state_fields: state_types,
182 return_type,
183 code,
184 language,
185 runtime_version: _,
186 imports,
187 packages,
188 } => {
189 let imports = imports
190 .iter()
191 .map(|s| QuotedString(s, '\'').to_string())
192 .join(",");
193 let packages = packages
194 .iter()
195 .map(|s| QuotedString(s, '\'').to_string())
196 .join(",");
197
198 write!(f, "( ")?;
199 write_comma_separated_list(f, arg_types)?;
200 write!(f, " ) STATE {{ ")?;
201 write_comma_separated_list(f, state_types)?;
202 write!(
203 f,
204 " }} RETURNS {return_type} LANGUAGE {language} IMPORTS = ({}) PACKAGES = ({}) AS $$\n{code}\n$$",
205 imports, packages
206 )?;
207 }
208 }
209 Ok(())
210 }
211}
212
213#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
214pub struct UDAFStateField {
215 pub name: Identifier,
216 pub type_name: TypeName,
217}
218
219impl Display for UDAFStateField {
220 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
221 write!(f, "{} {}", self.name, self.type_name)?;
222 Ok(())
223 }
224}
225
226#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
227pub struct CreateUDFStmt {
228 pub create_option: CreateOption,
229 pub udf_name: Identifier,
230 pub description: Option<String>,
231 pub definition: UDFDefinition,
232}
233
234impl Display for CreateUDFStmt {
235 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
236 write!(f, "CREATE")?;
237 if let CreateOption::CreateOrReplace = self.create_option {
238 write!(f, " OR REPLACE")?;
239 }
240 write!(f, " FUNCTION")?;
241 if let CreateOption::CreateIfNotExists = self.create_option {
242 write!(f, " IF NOT EXISTS")?;
243 }
244 write!(f, " {} {}", self.udf_name, self.definition)?;
245 if let Some(description) = &self.description {
246 write!(f, " DESC = '{description}'")?;
247 }
248 Ok(())
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
253pub struct AlterUDFStmt {
254 pub udf_name: Identifier,
255 pub description: Option<String>,
256 pub definition: UDFDefinition,
257}
258
259impl Display for AlterUDFStmt {
260 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
261 write!(f, "ALTER FUNCTION")?;
262 write!(f, " {} {}", self.udf_name, self.definition)?;
263 if let Some(description) = &self.description {
264 write!(f, " DESC = '{description}'")?;
265 }
266 Ok(())
267 }
268}