1mod data_type;
16mod ddl;
17mod operator;
18mod query;
19mod value;
20
21use std::fmt;
22
23pub use self::data_type::DataType;
24pub use self::ddl::{
25 AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef, TableConstraint,
26};
27pub use self::operator::{BinaryOperator, UnaryOperator};
28pub use self::query::{
29 Cte, Fetch, Join, JoinConstraint, JoinOperator, OrderByExpr, Query, Select, SelectItem,
30 SetExpr, SetOperator, TableAlias, TableFactor, TableWithJoins, Values,
31};
32pub use self::value::{DateTimeField, Value};
33
34struct DisplaySeparated<'a, T>
35where
36 T: fmt::Display,
37{
38 slice: &'a [T],
39 sep: &'static str,
40}
41
42impl<'a, T> fmt::Display for DisplaySeparated<'a, T>
43where
44 T: fmt::Display,
45{
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 let mut delim = "";
48 for t in self.slice {
49 write!(f, "{}", delim)?;
50 delim = self.sep;
51 write!(f, "{}", t)?;
52 }
53 Ok(())
54 }
55}
56
57fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
58where
59 T: fmt::Display,
60{
61 DisplaySeparated { slice, sep }
62}
63
64fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
65where
66 T: fmt::Display,
67{
68 DisplaySeparated { slice, sep: ", " }
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
73pub struct Ident {
74 pub value: String,
76 pub quote_style: Option<char>,
79}
80
81impl Ident {
82 pub fn new<S>(value: S) -> Self
84 where
85 S: Into<String>,
86 {
87 Ident {
88 value: value.into(),
89 quote_style: None,
90 }
91 }
92
93 pub fn with_quote<S>(quote: char, value: S) -> Self
96 where
97 S: Into<String>,
98 {
99 assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
100 Ident {
101 value: value.into(),
102 quote_style: Some(quote),
103 }
104 }
105}
106
107impl From<&str> for Ident {
108 fn from(value: &str) -> Self {
109 Ident {
110 value: value.to_string(),
111 quote_style: None,
112 }
113 }
114}
115
116impl fmt::Display for Ident {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 match self.quote_style {
119 Some(q) if q == '"' || q == '\'' || q == '`' => write!(f, "{}{}{}", q, self.value, q),
120 Some('[') => write!(f, "[{}]", self.value),
121 None => f.write_str(&self.value),
122 _ => panic!("unexpected quote style"),
123 }
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
129pub struct ObjectName(pub Vec<Ident>);
130
131impl fmt::Display for ObjectName {
132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133 write!(f, "{}", display_separated(&self.0, "."))
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Hash)]
143pub enum Expr {
144 Identifier(Ident),
146 Wildcard,
153 QualifiedWildcard(Vec<Ident>),
156 CompoundIdentifier(Vec<Ident>),
158 IsNull(Box<Expr>),
160 IsNotNull(Box<Expr>),
162 InList {
164 expr: Box<Expr>,
165 list: Vec<Expr>,
166 negated: bool,
167 },
168 ValueList(Vec<Expr>),
169 InSubquery {
171 expr: Box<Expr>,
172 subquery: Box<Query>,
173 negated: bool,
174 },
175 Between {
177 expr: Box<Expr>,
178 negated: bool,
179 low: Box<Expr>,
180 high: Box<Expr>,
181 },
182 BinaryOp {
184 left: Box<Expr>,
185 op: BinaryOperator,
186 right: Box<Expr>,
187 },
188 UnaryOp {
190 op: UnaryOperator,
191 expr: Box<Expr>,
192 },
193 Cast {
195 expr: Box<Expr>,
196 data_type: DataType,
197 },
198 Extract {
199 field: DateTimeField,
200 expr: Box<Expr>,
201 },
202 Collate {
204 expr: Box<Expr>,
205 collation: ObjectName,
206 },
207 Nested(Box<Expr>),
209 Value(Value),
211 Function(Function),
213 Case {
219 operand: Option<Box<Expr>>,
220 conditions: Vec<Expr>,
221 results: Vec<Expr>,
222 else_result: Option<Box<Expr>>,
223 },
224 Exists(Box<Query>),
227 Subquery(Box<Query>),
230}
231
232impl fmt::Display for Expr {
233 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234 match self {
235 Expr::Identifier(s) => write!(f, "{}", s),
236 Expr::Wildcard => f.write_str("*"),
237 Expr::QualifiedWildcard(q) => write!(f, "{}.*", display_separated(q, ".")),
238 Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
239 Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
240 Expr::IsNotNull(ast) => write!(f, "{} IS NOT NULL", ast),
241 Expr::InList {
242 expr,
243 list,
244 negated,
245 } => write!(
246 f,
247 "{} {}IN ({})",
248 expr,
249 if *negated { "NOT " } else { "" },
250 display_comma_separated(list)
251 ),
252 Expr::ValueList(list) => write!(f, "({})", display_comma_separated(list)),
253 Expr::InSubquery {
254 expr,
255 subquery,
256 negated,
257 } => write!(
258 f,
259 "{} {}IN ({})",
260 expr,
261 if *negated { "NOT " } else { "" },
262 subquery
263 ),
264 Expr::Between {
265 expr,
266 negated,
267 low,
268 high,
269 } => write!(
270 f,
271 "{} {}BETWEEN {} AND {}",
272 expr,
273 if *negated { "NOT " } else { "" },
274 low,
275 high
276 ),
277 Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
278 Expr::UnaryOp { op, expr } => write!(f, "{} {}", op, expr),
279 Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
280 Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
281 Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
282 Expr::Nested(ast) => write!(f, "({})", ast),
283 Expr::Value(v) => write!(f, "{}", v),
284 Expr::Function(fun) => write!(f, "{}", fun),
285 Expr::Case {
286 operand,
287 conditions,
288 results,
289 else_result,
290 } => {
291 f.write_str("CASE")?;
292 if let Some(operand) = operand {
293 write!(f, " {}", operand)?;
294 }
295 for (c, r) in conditions.iter().zip(results) {
296 write!(f, " WHEN {} THEN {}", c, r)?;
297 }
298
299 if let Some(else_result) = else_result {
300 write!(f, " ELSE {}", else_result)?;
301 }
302 f.write_str(" END")
303 }
304 Expr::Exists(s) => write!(f, "EXISTS ({})", s),
305 Expr::Subquery(s) => write!(f, "({})", s),
306 }
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub struct WindowSpec {
313 pub partition_by: Vec<Expr>,
314 pub order_by: Vec<OrderByExpr>,
315 pub window_frame: Option<WindowFrame>,
316}
317
318impl fmt::Display for WindowSpec {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 let mut delim = "";
321 if !self.partition_by.is_empty() {
322 delim = " ";
323 write!(
324 f,
325 "PARTITION BY {}",
326 display_comma_separated(&self.partition_by)
327 )?;
328 }
329 if !self.order_by.is_empty() {
330 f.write_str(delim)?;
331 delim = " ";
332 write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
333 }
334 if let Some(window_frame) = &self.window_frame {
335 if let Some(end_bound) = &window_frame.end_bound {
336 f.write_str(delim)?;
337 write!(
338 f,
339 "{} BETWEEN {} AND {}",
340 window_frame.units, window_frame.start_bound, end_bound
341 )?;
342 } else {
343 f.write_str(delim)?;
344 write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
345 }
346 }
347 Ok(())
348 }
349}
350
351#[derive(Debug, Clone, PartialEq, Eq, Hash)]
357pub struct WindowFrame {
358 pub units: WindowFrameUnits,
359 pub start_bound: WindowFrameBound,
360 pub end_bound: Option<WindowFrameBound>,
364 }
366
367#[derive(Debug, Clone, PartialEq, Eq, Hash)]
368pub enum WindowFrameUnits {
369 Rows,
370 Range,
371 Groups,
372}
373
374impl fmt::Display for WindowFrameUnits {
375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376 f.write_str(match self {
377 WindowFrameUnits::Rows => "ROWS",
378 WindowFrameUnits::Range => "RANGE",
379 WindowFrameUnits::Groups => "GROUPS",
380 })
381 }
382}
383
384impl FromStr for WindowFrameUnits {
385 type Err = ParserError;
386
387 fn from_str(s: &str) -> Result<Self, Self::Err> {
388 match s {
389 "ROWS" => Ok(WindowFrameUnits::Rows),
390 "RANGE" => Ok(WindowFrameUnits::Range),
391 "GROUPS" => Ok(WindowFrameUnits::Groups),
392 _ => Err(ParserError::ParserError(format!(
393 "Expected ROWS, RANGE, or GROUPS, found: {}",
394 s
395 ))),
396 }
397 }
398}
399
400#[derive(Debug, Clone, PartialEq, Eq, Hash)]
402pub enum WindowFrameBound {
403 CurrentRow,
405 Preceding(Option<u64>),
407 Following(Option<u64>),
409}
410
411impl fmt::Display for WindowFrameBound {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 match self {
414 WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
415 WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
416 WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
417 WindowFrameBound::Preceding(Some(n)) => write!(f, "{} PRECEDING", n),
418 WindowFrameBound::Following(Some(n)) => write!(f, "{} FOLLOWING", n),
419 }
420 }
421}
422
423#[allow(clippy::large_enum_variant)]
425#[derive(Debug, Clone, PartialEq, Eq, Hash)]
426pub enum Statement {
427 Query(Box<Query>),
429 Insert {
431 table_name: ObjectName,
433 columns: Vec<Ident>,
435 source: Box<Query>,
437 },
438 Copy {
439 table_name: ObjectName,
441 columns: Vec<Ident>,
443 values: Vec<Option<String>>,
445 },
446 Update {
448 table_name: ObjectName,
450 assignments: Vec<Assignment>,
452 selection: Option<Expr>,
454 },
455 Delete {
457 table_name: ObjectName,
459 selection: Option<Expr>,
461 },
462 CreateView {
464 name: ObjectName,
466 columns: Vec<Ident>,
467 query: Box<Query>,
468 materialized: bool,
469 with_options: Vec<SqlOption>,
470 },
471 CreateTable {
473 if_not_exists: bool,
474 name: ObjectName,
476 columns: Vec<ColumnDef>,
478 constraints: Vec<TableConstraint>,
479 with_options: Vec<SqlOption>,
480 external: bool,
481 file_format: Option<FileFormat>,
482 location: Option<String>,
483 },
484 AlterTable {
486 name: ObjectName,
488 operation: AlterTableOperation,
489 },
490 Drop {
492 object_type: ObjectType,
494 if_exists: bool,
496 names: Vec<ObjectName>,
498 cascade: bool,
501 },
502}
503
504impl fmt::Display for Statement {
505 #[allow(clippy::cognitive_complexity)]
508 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
509 match self {
510 Statement::Query(s) => write!(f, "{}", s),
511 Statement::Insert {
512 table_name,
513 columns,
514 source,
515 } => {
516 write!(f, "INSERT INTO {} ", table_name)?;
517 if !columns.is_empty() {
518 write!(f, "({}) ", display_comma_separated(columns))?;
519 }
520 write!(f, "{}", source)
521 }
522 Statement::Copy {
523 table_name,
524 columns,
525 values,
526 } => {
527 write!(f, "COPY {}", table_name)?;
528 if !columns.is_empty() {
529 write!(f, " ({})", display_comma_separated(columns))?;
530 }
531 write!(f, " FROM stdin; ")?;
532 if !values.is_empty() {
533 writeln!(f)?;
534 let mut delim = "";
535 for v in values {
536 write!(f, "{}", delim)?;
537 delim = "\t";
538 if let Some(v) = v {
539 write!(f, "{}", v)?;
540 } else {
541 write!(f, "\\N")?;
542 }
543 }
544 }
545 write!(f, "\n\\.")
546 }
547 Statement::Update {
548 table_name,
549 assignments,
550 selection,
551 } => {
552 write!(f, "UPDATE {}", table_name)?;
553 if !assignments.is_empty() {
554 write!(f, " SET ")?;
555 write!(f, "{}", display_comma_separated(assignments))?;
556 }
557 if let Some(selection) = selection {
558 write!(f, " WHERE {}", selection)?;
559 }
560 Ok(())
561 }
562 Statement::Delete {
563 table_name,
564 selection,
565 } => {
566 write!(f, "DELETE FROM {}", table_name)?;
567 if let Some(selection) = selection {
568 write!(f, " WHERE {}", selection)?;
569 }
570 Ok(())
571 }
572 Statement::CreateView {
573 name,
574 columns,
575 query,
576 materialized,
577 with_options,
578 } => {
579 write!(f, "CREATE")?;
580 if *materialized {
581 write!(f, " MATERIALIZED")?;
582 }
583
584 write!(f, " VIEW {}", name)?;
585
586 if !with_options.is_empty() {
587 write!(f, " WITH ({})", display_comma_separated(with_options))?;
588 }
589
590 if !columns.is_empty() {
591 write!(f, " ({})", display_comma_separated(columns))?;
592 }
593
594 write!(f, " AS {}", query)
595 }
596 Statement::CreateTable {
597 name,
598 if_not_exists,
599 columns,
600 constraints,
601 with_options,
602 external,
603 file_format,
604 location,
605 } => {
606 write!(
607 f,
608 "CREATE {}TABLE {}{} ({}",
609 if *external { "EXTERNAL " } else { "" },
610 if *if_not_exists { "IF NOT EXISTS " } else { "" },
611 name,
612 display_comma_separated(columns)
613 )?;
614 if !constraints.is_empty() {
615 write!(f, ", {}", display_comma_separated(constraints))?;
616 }
617 write!(f, ")")?;
618
619 if *external {
620 write!(
621 f,
622 " STORED AS {} LOCATION '{}'",
623 file_format.as_ref().unwrap(),
624 location.as_ref().unwrap()
625 )?;
626 }
627 if !with_options.is_empty() {
628 write!(f, " WITH ({})", display_comma_separated(with_options))?;
629 }
630 Ok(())
631 }
632 Statement::AlterTable { name, operation } => {
633 write!(f, "ALTER TABLE {} {}", name, operation)
634 }
635 Statement::Drop {
636 object_type,
637 if_exists,
638 names,
639 cascade,
640 } => write!(
641 f,
642 "DROP {}{} {}{}",
643 object_type,
644 if *if_exists { " IF EXISTS" } else { "" },
645 display_comma_separated(names),
646 if *cascade { " CASCADE" } else { "" },
647 ),
648 }
649 }
650}
651
652#[derive(Debug, Clone, PartialEq, Eq, Hash)]
654pub struct Assignment {
655 pub id: Ident,
656 pub value: Expr,
657}
658
659impl fmt::Display for Assignment {
660 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
661 write!(f, "{} = {}", self.id, self.value)
662 }
663}
664
665#[derive(Debug, Clone, PartialEq, Eq, Hash)]
667pub struct Function {
668 pub name: ObjectName,
669 pub args: Vec<Expr>,
670 pub over: Option<WindowSpec>,
671 pub distinct: bool,
673}
674
675impl fmt::Display for Function {
676 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
677 write!(
678 f,
679 "{}({}{})",
680 self.name,
681 if self.distinct { "DISTINCT " } else { "" },
682 display_comma_separated(&self.args),
683 )?;
684 if let Some(o) = &self.over {
685 write!(f, " OVER ({})", o)?;
686 }
687 Ok(())
688 }
689}
690
691#[derive(Debug, Clone, PartialEq, Eq, Hash)]
693pub enum FileFormat {
694 TEXTFILE,
695 SEQUENCEFILE,
696 ORC,
697 PARQUET,
698 AVRO,
699 RCFILE,
700 JSONFILE,
701}
702
703impl fmt::Display for FileFormat {
704 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
705 use self::FileFormat::*;
706 f.write_str(match self {
707 TEXTFILE => "TEXTFILE",
708 SEQUENCEFILE => "SEQUENCEFILE",
709 ORC => "ORC",
710 PARQUET => "PARQUET",
711 AVRO => "AVRO",
712 RCFILE => "RCFILE",
713 JSONFILE => "TEXTFILE",
714 })
715 }
716}
717
718use crate::parser::ParserError;
719use std::str::FromStr;
720impl FromStr for FileFormat {
721 type Err = ParserError;
722
723 fn from_str(s: &str) -> Result<Self, Self::Err> {
724 use self::FileFormat::*;
725 match s {
726 "TEXTFILE" => Ok(TEXTFILE),
727 "SEQUENCEFILE" => Ok(SEQUENCEFILE),
728 "ORC" => Ok(ORC),
729 "PARQUET" => Ok(PARQUET),
730 "AVRO" => Ok(AVRO),
731 "RCFILE" => Ok(RCFILE),
732 "JSONFILE" => Ok(JSONFILE),
733 _ => Err(ParserError::ParserError(format!(
734 "Unexpected file format: {}",
735 s
736 ))),
737 }
738 }
739}
740
741#[derive(Debug, Clone, PartialEq, Eq, Hash)]
742pub enum ObjectType {
743 Table,
744 View,
745}
746
747impl fmt::Display for ObjectType {
748 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
749 f.write_str(match self {
750 ObjectType::Table => "TABLE",
751 ObjectType::View => "VIEW",
752 })
753 }
754}
755
756#[derive(Debug, Clone, PartialEq, Eq, Hash)]
757pub struct SqlOption {
758 pub name: Ident,
759 pub value: Value,
760}
761
762impl fmt::Display for SqlOption {
763 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
764 write!(f, "{} = {}", self.name, self.value)
765 }
766}