1use serde::Serialize;
16use sqlparser::ast::{
17 Insert as SpInsert, ObjectName, ObjectNamePart, Parens, Query, SetExpr, Statement, TableObject,
18 UnaryOperator, ValueWithSpan, Values,
19};
20use sqlparser::parser::ParserError;
21use sqlparser_derive::{Visit, VisitMut};
22
23use crate::ast::{Expr, Value};
24use crate::error::{Result, UnsupportedSnafu};
25use crate::statements::query::Query as GtQuery;
26
27#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
28pub struct Insert {
29 pub inner: Statement,
31}
32
33macro_rules! parse_fail {
34 ($expr: expr) => {
35 return crate::error::ParseSqlValueSnafu {
36 msg: format!("{:?}", $expr),
37 }
38 .fail();
39 };
40}
41
42impl Insert {
43 pub fn table_name(&self) -> Result<&ObjectName> {
44 match &self.inner {
45 Statement::Insert(insert) => {
46 let TableObject::TableName(name) = &insert.table else {
47 return UnsupportedSnafu {
48 keyword: "TABLE FUNCTION".to_string(),
49 }
50 .fail();
51 };
52 Ok(name)
53 }
54 _ => unreachable!(),
55 }
56 }
57
58 pub fn columns(&self) -> Vec<&String> {
59 match &self.inner {
60 Statement::Insert(insert) => insert
61 .columns
62 .iter()
63 .filter_map(single_part_column_ident)
64 .map(|ident| &ident.value)
65 .collect(),
66 _ => unreachable!(),
67 }
68 }
69
70 pub fn values_body(&self) -> Result<Vec<Vec<Value>>> {
72 match &self.inner {
73 Statement::Insert(SpInsert {
74 source:
75 Some(box Query {
76 body: box SetExpr::Values(Values { rows, .. }),
77 ..
78 }),
79 ..
80 }) => sql_exprs_to_values(rows),
81 _ => unreachable!(),
82 }
83 }
84
85 pub fn can_extract_values(&self) -> bool {
88 match &self.inner {
89 Statement::Insert(SpInsert {
90 source:
91 Some(box Query {
92 body: box SetExpr::Values(Values { rows, .. }),
93 ..
94 }),
95 ..
96 }) => rows.iter().all(|es| {
97 es.iter().all(|expr| match expr {
98 Expr::Value(_) => true,
99 Expr::Identifier(ident) => {
100 if ident.quote_style.is_none() {
101 ident.value.to_lowercase() == "default"
102 } else {
103 ident.quote_style == Some('"')
104 }
105 }
106 Expr::UnaryOp { op, expr } => {
107 matches!(op, UnaryOperator::Minus | UnaryOperator::Plus)
108 && matches!(
109 &**expr,
110 Expr::Value(ValueWithSpan {
111 value: Value::Number(_, _),
112 ..
113 })
114 )
115 }
116 _ => false,
117 })
118 }),
119 _ => false,
120 }
121 }
122
123 pub fn has_non_values_query_source(&self) -> bool {
125 match &self.inner {
126 Statement::Insert(SpInsert {
127 source: Some(box query),
128 ..
129 }) => !matches!(&*query.body, SetExpr::Values(_)),
130 _ => false,
131 }
132 }
133
134 pub fn query_body(&self) -> Result<Option<GtQuery>> {
135 Ok(match &self.inner {
136 Statement::Insert(SpInsert {
137 source: Some(box query),
138 ..
139 }) => Some(query.clone().try_into()?),
140 _ => None,
141 })
142 }
143}
144
145fn sql_exprs_to_values(exprs: &[Parens<Vec<Expr>>]) -> Result<Vec<Vec<Value>>> {
146 let mut values = Vec::with_capacity(exprs.len());
147 for es in exprs.iter() {
148 let mut vs = Vec::with_capacity(es.len());
149 for expr in es.iter() {
150 vs.push(match expr {
151 Expr::Value(v) => v.value.clone(),
152 Expr::Identifier(ident) => {
153 if ident.quote_style.is_none() {
154 if ident.value.to_lowercase() == "default" {
156 Value::Placeholder(ident.value.clone())
157 } else {
158 parse_fail!(expr);
159 }
160 } else {
161 if ident.quote_style == Some('"') {
163 Value::SingleQuotedString(ident.value.clone())
164 } else {
165 parse_fail!(expr);
166 }
167 }
168 }
169 Expr::UnaryOp { op, expr }
170 if matches!(op, UnaryOperator::Minus | UnaryOperator::Plus) =>
171 {
172 if let Expr::Value(ValueWithSpan {
173 value: Value::Number(s, b),
174 ..
175 }) = &**expr
176 {
177 match op {
178 UnaryOperator::Minus => Value::Number(format!("-{s}"), *b),
179 UnaryOperator::Plus => Value::Number(s.clone(), *b),
180 _ => unreachable!(),
181 }
182 } else {
183 parse_fail!(expr);
184 }
185 }
186 _ => {
187 parse_fail!(expr);
188 }
189 });
190 }
191 values.push(vs);
192 }
193 Ok(values)
194}
195
196fn single_part_column_ident(name: &ObjectName) -> Option<&sqlparser::ast::Ident> {
197 let [ObjectNamePart::Identifier(ident)] = name.0.as_slice() else {
198 return None;
199 };
200 Some(ident)
201}
202
203impl TryFrom<Statement> for Insert {
204 type Error = ParserError;
205
206 fn try_from(value: Statement) -> std::result::Result<Self, Self::Error> {
207 let Statement::Insert(insert) = &value else {
208 return Err(ParserError::ParserError(format!(
209 "Not expected to be {value}"
210 )));
211 };
212
213 if let Some(column) = insert
214 .columns
215 .iter()
216 .find(|column| single_part_column_ident(column).is_none())
217 {
218 return Err(ParserError::ParserError(format!(
219 "Expected a single-part insert column name, found {column}"
220 )));
221 }
222
223 Ok(Insert { inner: value })
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use crate::dialect::GreptimeDbDialect;
231 use crate::parser::{ParseOptions, ParserContext};
232 use crate::statements::statement::Statement;
233
234 #[test]
235 fn test_insert_value_with_unary_op() {
236 let sql = "INSERT INTO my_table VALUES(-1)";
238 let stmt =
239 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
240 .unwrap()
241 .remove(0);
242 match stmt {
243 Statement::Insert(insert) => {
244 let values = insert.values_body().unwrap();
245 assert_eq!(values, vec![vec![Value::Number("-1".to_string(), false)]]);
246 }
247 _ => unreachable!(),
248 }
249
250 let sql = "INSERT INTO my_table VALUES(+1)";
252 let stmt =
253 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
254 .unwrap()
255 .remove(0);
256 match stmt {
257 Statement::Insert(insert) => {
258 let values = insert.values_body().unwrap();
259 assert_eq!(values, vec![vec![Value::Number("1".to_string(), false)]]);
260 }
261 _ => unreachable!(),
262 }
263 }
264
265 #[test]
266 fn test_insert_column_names_are_single_identifiers() {
267 let stmt = ParserContext::create_with_dialect(
268 "INSERT INTO my_table (host, \"value\") VALUES (1, 2)",
269 &GreptimeDbDialect {},
270 ParseOptions::default(),
271 )
272 .unwrap()
273 .remove(0);
274 let Statement::Insert(insert) = stmt else {
275 unreachable!()
276 };
277 assert_eq!(insert.columns(), vec!["host", "value"]);
278
279 let result = ParserContext::create_with_dialect(
280 "INSERT INTO my_table (metric.host) VALUES (1)",
281 &GreptimeDbDialect {},
282 ParseOptions::default(),
283 );
284 let error = result.unwrap_err().to_string();
285 assert!(
286 error.contains("Expected a single-part insert column name, found metric.host"),
287 "unexpected error: {error}"
288 );
289 }
290
291 #[test]
292 fn test_insert_value_with_default() {
293 let sql = "INSERT INTO my_table VALUES(default)";
295 let stmt =
296 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
297 .unwrap()
298 .remove(0);
299 match stmt {
300 Statement::Insert(insert) => {
301 let values = insert.values_body().unwrap();
302 assert_eq!(values, vec![vec![Value::Placeholder("default".to_owned())]]);
303 }
304 _ => unreachable!(),
305 }
306 }
307
308 #[test]
309 fn test_insert_value_with_default_uppercase() {
310 let sql = "INSERT INTO my_table VALUES(DEFAULT)";
312 let stmt =
313 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
314 .unwrap()
315 .remove(0);
316 match stmt {
317 Statement::Insert(insert) => {
318 let values = insert.values_body().unwrap();
319 assert_eq!(values, vec![vec![Value::Placeholder("DEFAULT".to_owned())]]);
320 }
321 _ => unreachable!(),
322 }
323 }
324
325 #[test]
326 fn test_insert_value_with_quoted_string() {
327 let sql = "INSERT INTO my_table VALUES('default')";
329 let stmt =
330 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
331 .unwrap()
332 .remove(0);
333 match stmt {
334 Statement::Insert(insert) => {
335 let values = insert.values_body().unwrap();
336 assert_eq!(
337 values,
338 vec![vec![Value::SingleQuotedString("default".to_owned())]]
339 );
340 }
341 _ => unreachable!(),
342 }
343
344 let sql = "INSERT INTO my_table VALUES(\"default\")";
346 let stmt =
347 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
348 .unwrap()
349 .remove(0);
350 match stmt {
351 Statement::Insert(insert) => {
352 let values = insert.values_body().unwrap();
353 assert_eq!(
354 values,
355 vec![vec![Value::SingleQuotedString("default".to_owned())]]
356 );
357 }
358 _ => unreachable!(),
359 }
360
361 let sql = "INSERT INTO my_table VALUES(`default`)";
362 let stmt =
363 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
364 .unwrap()
365 .remove(0);
366 match stmt {
367 Statement::Insert(insert) => {
368 assert!(insert.values_body().is_err());
369 }
370 _ => unreachable!(),
371 }
372 }
373
374 #[test]
375 fn test_insert_select() {
376 let sql = "INSERT INTO my_table select * from other_table";
377 let stmt =
378 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
379 .unwrap()
380 .remove(0);
381 match stmt {
382 Statement::Insert(insert) => {
383 let q = insert.query_body().unwrap().unwrap();
384 assert!(insert.has_non_values_query_source());
385 assert!(matches!(
386 q.inner,
387 Query {
388 body: box SetExpr::Select { .. },
389 ..
390 }
391 ));
392 }
393 _ => unreachable!(),
394 }
395 }
396
397 #[test]
398 fn test_has_non_values_query_source() {
399 let cases = [
400 ("INSERT INTO my_table SELECT * FROM other_table", true),
401 (
402 "INSERT INTO my_table WITH cte AS (SELECT * FROM other_table) SELECT * FROM cte",
403 true,
404 ),
405 (
406 "INSERT INTO my_table SELECT * FROM t1 UNION ALL SELECT * FROM t2",
407 true,
408 ),
409 ("INSERT INTO my_table VALUES(1)", false),
410 ("INSERT INTO my_table VALUES(now())", false),
411 ("INSERT INTO my_table VALUES(1 + 1)", false),
412 ];
413
414 for (sql, expected) in cases {
415 let stmt = ParserContext::create_with_dialect(
416 sql,
417 &GreptimeDbDialect {},
418 ParseOptions::default(),
419 )
420 .unwrap()
421 .remove(0);
422 match stmt {
423 Statement::Insert(insert) => {
424 assert_eq!(insert.has_non_values_query_source(), expected, "{sql}");
425 }
426 _ => unreachable!(),
427 }
428 }
429 }
430}