1#![allow(unused)]
2
3use std::{
4 any::Any,
5 borrow::Cow,
6 io::{Cursor, Write},
7 ops::Deref,
8 path::Display,
9 slice,
10};
11
12use sqlparser::{
13 ast::{
14 Assignment, AssignmentTarget, BinaryOperator, CastKind, CharacterLength, ColumnDef,
15 ColumnOptionDef, CreateIndex, CreateTable as SqlParserCreateTable, CreateTableOptions,
16 Delete, ExactNumberInfo, Expr, FromTable, FunctionArguments, HiveDistributionStyle,
17 HiveFormat, Ident, IndexColumn, JoinConstraint, ObjectName, ObjectNamePart, ObjectType,
18 OrderByExpr, Query, ReferentialAction, SelectItem, SetExpr, SqliteOnConflict, Statement,
19 Table, TableConstraint, TableFactor, TableWithJoins, UpdateTableFromKind, Value,
20 ValueWithSpan,
21 },
22 dialect::{self, Dialect, MySqlDialect, PostgreSqlDialect, SQLiteDialect},
23 keywords::Keyword,
24 parser::Parser,
25 tokenizer::{Token, Word},
26};
27
28use crate::{Error, Result};
29
30#[derive(Debug, Clone, Copy, PartialEq)]
32pub enum DataType {
33 SmallSerial,
34 Serial,
35 BigSerial,
36 I16,
37 I32,
38 I64,
39 F32,
40 F64,
41 Bool,
42 String,
43 Char(u64),
44 VarChar(u64),
45 Bytes,
46 Json,
47 Uuid,
48 Decimal { precision: u64, scale: i64 },
49 Date,
50 Time,
51 Timestamp,
52}
53
54impl TryFrom<&sqlparser::ast::DataType> for DataType {
55 type Error = Error;
56
57 fn try_from(value: &sqlparser::ast::DataType) -> Result<Self, Self::Error> {
58 let dt = match value {
59 sqlparser::ast::DataType::SmallInt(_) => DataType::I16,
60 sqlparser::ast::DataType::Int(_) => DataType::I32,
61 sqlparser::ast::DataType::Integer(_) => DataType::I32,
62 sqlparser::ast::DataType::BigInt(_) => DataType::I64,
63 sqlparser::ast::DataType::Real => DataType::F32,
64 sqlparser::ast::DataType::Double(_) => DataType::F64,
65 sqlparser::ast::DataType::DoublePrecision => DataType::F64,
66 sqlparser::ast::DataType::Bool => DataType::Bool,
67 sqlparser::ast::DataType::Boolean => DataType::Bool,
68 sqlparser::ast::DataType::Text => DataType::String,
69 sqlparser::ast::DataType::Char(Some(CharacterLength::IntegerLength {
70 length, ..
71 })) => DataType::Char(*length),
72 sqlparser::ast::DataType::Varchar(Some(CharacterLength::IntegerLength {
73 length,
74 ..
75 })) => DataType::VarChar(*length),
76 sqlparser::ast::DataType::Bytea => DataType::Bytes,
77 sqlparser::ast::DataType::JSON => DataType::Json,
78 sqlparser::ast::DataType::Uuid => DataType::Uuid,
79 sqlparser::ast::DataType::Decimal(ExactNumberInfo::PrecisionAndScale(
80 precision,
81 scale,
82 )) => DataType::Decimal {
83 precision: *precision,
84 scale: *scale,
85 },
86 sqlparser::ast::DataType::Numeric(ExactNumberInfo::PrecisionAndScale(
87 precision,
88 scale,
89 )) => DataType::Decimal {
90 precision: *precision,
91 scale: *scale,
92 },
93 sqlparser::ast::DataType::Custom(ObjectName(name_parts), _) => {
94 match extract_serial(name_parts) {
95 Some(dt) => dt,
96 None => Err(Error::DataType {
97 data_type: Box::new(value.clone()),
98 })?,
99 }
100 }
101 sqlparser::ast::DataType::Date => DataType::Date,
102 sqlparser::ast::DataType::Time(_, _) => DataType::Time,
103 sqlparser::ast::DataType::Timestamp(_, _) => DataType::Timestamp,
104 sqlparser::ast::DataType::Datetime(_) => DataType::Timestamp,
105 _ => Err(Error::DataType {
106 data_type: Box::new(value.clone()),
107 })?,
108 };
109 Ok(dt)
110 }
111}
112
113fn extract_serial(name_parts: &[ObjectNamePart]) -> Option<DataType> {
114 let name = match name_parts.first() {
115 None => return None,
116 Some(ObjectNamePart::Function(_)) => return None,
117 Some(ObjectNamePart::Identifier(name)) => name,
118 };
119 let name = name.value.to_ascii_lowercase();
120 match name.as_str() {
121 "bigserial" => Some(DataType::BigSerial),
122 "serial" => Some(DataType::Serial),
123 "smallserial" => Some(DataType::SmallSerial),
124 _ => None,
125 }
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct Column {
130 pub name: String,
131 pub data_type: DataType,
132 pub options: ColumnOptions,
133}
134
135impl TryFrom<&ColumnDef> for Column {
136 type Error = Error;
137
138 fn try_from(value: &ColumnDef) -> std::result::Result<Self, Self::Error> {
139 let ColumnDef {
140 name,
141 data_type,
142 options,
143 } = value;
144 Ok(Self {
145 name: name.value.clone(),
146 data_type: data_type.try_into()?,
147 options: ColumnOptions::try_from(options.as_slice())?,
148 })
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq)]
153pub struct ColumnOptions(u32);
154
155#[derive(Debug, Clone, Copy, PartialEq)]
156#[repr(u32)]
157pub enum ColumnOption {
158 PrimaryKey = 1,
159 AutoInrement = 1 << 1,
160 Nullable = 1 << 2,
161 NotNull = 1 << 3,
162 Unique = 1 << 4,
163}
164
165impl ColumnOptions {
166 fn new() -> Self {
167 Self(0)
168 }
169
170 fn set_primary_key(mut self) -> Self {
171 self.0 |= ColumnOption::PrimaryKey as u32;
172 self
173 }
174
175 fn is_primary_key(self) -> bool {
176 self.0 & ColumnOption::PrimaryKey as u32 != 0
177 }
178
179 fn set_auto_increment(mut self) -> Self {
180 self.0 |= ColumnOption::AutoInrement as u32;
181 self
182 }
183
184 fn unset_auto_increment(mut self) -> Self {
185 self.0 &= !(ColumnOption::AutoInrement as u32);
186 self
187 }
188
189 fn is_auto_increment(self) -> bool {
190 self.0 & ColumnOption::AutoInrement as u32 != 0
191 }
192
193 fn set_nullable(mut self) -> Self {
194 self.0 |= ColumnOption::Nullable as u32;
195 self
196 }
197
198 fn is_nullable(self) -> bool {
199 self.0 & ColumnOption::Nullable as u32 != 0
200 }
201
202 fn set_not_null(mut self) -> Self {
203 self.0 |= ColumnOption::NotNull as u32;
204 self
205 }
206
207 fn is_not_null(self) -> bool {
208 self.0 & ColumnOption::NotNull as u32 != 0
209 }
210
211 fn set_unique(mut self) -> Self {
212 self.0 |= ColumnOption::Unique as u32;
213 self
214 }
215
216 fn is_unique(self) -> bool {
217 self.0 & ColumnOption::Unique as u32 != 0
218 }
219
220 #[allow(clippy::type_complexity)]
221 fn mapping() -> &'static [(ColumnOption, fn(Self) -> bool)] {
222 &[
223 (ColumnOption::PrimaryKey, ColumnOptions::is_primary_key),
224 (ColumnOption::AutoInrement, ColumnOptions::is_auto_increment),
225 (ColumnOption::Nullable, ColumnOptions::is_nullable),
226 (ColumnOption::NotNull, ColumnOptions::is_not_null),
227 (ColumnOption::Unique, ColumnOptions::is_unique),
228 ]
229 }
230}
231
232pub struct ColumnIterator {
233 column_options: ColumnOptions,
234 pos: usize,
235}
236
237impl Iterator for ColumnIterator {
238 type Item = ColumnOption;
239
240 fn next(&mut self) -> Option<Self::Item> {
241 let mapping = ColumnOptions::mapping();
242 loop {
243 if self.pos >= mapping.len() {
244 return None;
245 }
246 let (option, check) = mapping[self.pos];
247 self.pos += 1;
248 if check(self.column_options) {
249 return Some(option);
250 }
251 }
252 }
253}
254
255impl IntoIterator for ColumnOptions {
256 type Item = ColumnOption;
257 type IntoIter = ColumnIterator;
258
259 fn into_iter(self) -> Self::IntoIter {
260 ColumnIterator {
261 column_options: self,
262 pos: 0,
263 }
264 }
265}
266
267impl std::fmt::Display for ColumnOptions {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 for option in self.into_iter() {
270 write!(f, "{option:?} ")?;
271 }
272 Ok(())
273 }
274}
275
276impl TryFrom<&[ColumnOptionDef]> for ColumnOptions {
277 type Error = Error;
278
279 fn try_from(values: &[ColumnOptionDef]) -> Result<Self, Self::Error> {
280 values.iter().try_fold(
281 ColumnOptions::new(),
282 |mut options, value| -> Result<_, Error> {
283 let options = match &value.option {
284 sqlparser::ast::ColumnOption::Unique { is_primary, .. } if *is_primary => {
285 options.set_primary_key()
286 }
287 sqlparser::ast::ColumnOption::NotNull => options.set_not_null(),
288 sqlparser::ast::ColumnOption::Null => options.set_nullable(),
289 option if is_auto_increment_option(option) => options.set_auto_increment(),
290 option => Err(Error::ColumnOption {
291 option: Box::new(option.clone()),
292 })?,
293 };
294 Ok(options)
295 },
296 )
297 }
298}
299
300fn is_auto_increment_option(option: &sqlparser::ast::ColumnOption) -> bool {
301 match option {
302 sqlparser::ast::ColumnOption::DialectSpecific(tokens) if tokens.len() == 1 => tokens
303 .first()
304 .map(|token| match token {
305 Token::Word(Word { keyword, .. }) => {
306 *keyword == Keyword::AUTOINCREMENT || *keyword == Keyword::AUTO_INCREMENT
307 }
308 _ => false,
309 })
310 .unwrap(),
311 _ => false,
312 }
313}
314
315#[derive(Debug, Clone, PartialEq)]
316pub enum Constraint {
317 PrimaryKey(Vec<String>),
318 ForeignKey {
319 columns: Vec<String>,
320 referred_columns: Vec<String>,
321 foreign_table: String,
322 on_delete: Option<OnDeleteAction>,
323 },
324}
325
326#[derive(Debug, Clone, PartialEq)]
327pub enum OnDeleteAction {
328 Cascade,
329 SetNull,
330 Restrict,
331}
332
333impl TryFrom<&ReferentialAction> for OnDeleteAction {
334 type Error = Error;
335
336 fn try_from(value: &ReferentialAction) -> Result<Self, Self::Error> {
337 match value {
338 ReferentialAction::Cascade => Ok(OnDeleteAction::Cascade),
339 ReferentialAction::Restrict => Ok(OnDeleteAction::Restrict),
340 ReferentialAction::SetNull => Ok(OnDeleteAction::SetNull),
341 other => Err(Error::OnDeleteConstrait {
342 referential_action: *other,
343 })?,
344 }
345 }
346}
347
348#[derive(Debug, Clone, PartialEq)]
349pub struct Constraints(Vec<Constraint>);
350
351impl Constraints {
352 fn len(&self) -> usize {
353 self.0.len()
354 }
355}
356
357#[derive(Debug)]
358pub struct ConstraintsIter<'a> {
359 constraints: &'a Constraints,
360 pos: usize,
361}
362
363impl<'a> Iterator for ConstraintsIter<'a> {
364 type Item = &'a Constraint;
365
366 fn next(&mut self) -> Option<Self::Item> {
367 if self.constraints.0.len() > self.pos {
368 let item = &self.constraints.0[self.pos];
369 self.pos += 1;
370 return Some(item);
371 }
372 None
373 }
374}
375
376impl<'a> IntoIterator for &'a Constraints {
377 type IntoIter = ConstraintsIter<'a>;
378 type Item = &'a Constraint;
379
380 fn into_iter(self) -> Self::IntoIter {
381 ConstraintsIter {
382 pos: 0,
383 constraints: self,
384 }
385 }
386}
387
388impl TryFrom<&[TableConstraint]> for Constraints {
389 type Error = Error;
390
391 fn try_from(value: &[TableConstraint]) -> Result<Self, Self::Error> {
392 let constraints = value
393 .iter()
394 .map(|constraint| -> Result<_> {
395 let res = match constraint {
396 TableConstraint::PrimaryKey {
397 columns,
398 name,
399 index_name,
400 index_type,
401 index_options,
402 characteristics,
403 } => {
404 if name.is_some() {
405 Err(Error::PrimaryKey { reason: "name" })?
406 }
407 if index_name.is_some() {
408 Err(Error::PrimaryKey {
409 reason: "index name",
410 })?
411 }
412 if index_type.is_some() {
413 Err(Error::PrimaryKey {
414 reason: "index type",
415 })?
416 }
417 if !index_options.is_empty() {
418 Err(Error::PrimaryKey {
419 reason: "index options",
420 })?
421 }
422 if characteristics.is_some() {
423 Err(Error::PrimaryKey {
424 reason: "characteristics",
425 })?
426 }
427 let columns = columns
428 .iter()
429 .map(
430 |IndexColumn {
431 column,
432 operator_class,
433 }| {
434 if operator_class.is_some() {
435 Err(Error::PrimaryKey {
436 reason: "operator class",
437 })?
438 };
439 let OrderByExpr {
440 expr,
441 options,
442 with_fill,
443 } = column;
444 if with_fill.is_some() {
445 Err(Error::PrimaryKey {
446 reason: "`WITH FILL`",
447 })?
448 }
449 if options.nulls_first.is_some() || options.asc.is_some() {
450 Err(Error::PrimaryKey { reason: "options" })?
451 }
452 match expr {
453 Expr::Identifier(ident) => Ok(ident.value.clone()),
454 _ => Err(Error::PrimaryKeyWithExpression {
455 expr: Box::new(expr.clone()),
456 })?,
457 }
458 },
459 )
460 .collect::<Result<Vec<_>>>()?;
461 Constraint::PrimaryKey(columns)
462 }
463 TableConstraint::ForeignKey {
464 name,
465 columns,
466 foreign_table,
467 referred_columns,
468 on_delete,
469 on_update,
470 characteristics,
471 index_name,
472 } => {
473 if name.is_some() {
474 Err(Error::ForeignKey {
475 reason: "constraint",
476 })?
477 }
478 if on_update.is_some() {
479 Err(Error::ForeignKey {
480 reason: "on update",
481 })?
482 }
483 if characteristics.is_some() {
484 Err(Error::ForeignKey {
485 reason: "characteristics",
486 })?
487 }
488 let on_delete = match on_delete {
489 None => None,
490 Some(action) => Some(action.try_into()?),
491 };
492 let columns = columns
493 .iter()
494 .map(|Ident { value, .. }| value.clone())
495 .collect();
496 let referred_columns = referred_columns
497 .iter()
498 .map(|Ident { value, .. }| value.clone())
499 .collect();
500 let foreign_table = Ast::parse_object_name(foreign_table)?;
501 Constraint::ForeignKey {
502 columns,
503 referred_columns,
504 foreign_table,
505 on_delete,
506 }
507 }
508 _ => Err(Error::TableConstraint {
509 constraint: Box::new(constraint.clone()),
510 })?,
511 };
512 Ok(res)
513 })
514 .collect::<Result<Vec<Constraint>, _>>()?;
515 Ok(Constraints(constraints))
516 }
517}
518
519#[derive(Debug, Clone, PartialEq)]
520pub enum Ast {
521 CreateTable {
522 if_not_exists: bool,
523 name: String,
524 columns: Vec<Column>,
525 constraints: Constraints,
526 },
527 AlterTable {
528 name: String,
529 operation: AlterTableOperation,
530 },
531 CreateIndex {
532 unique: bool,
533 name: String,
534 table: String,
535 columns: Vec<String>,
536 },
537 Select {
538 distinct: bool,
539 projections: Vec<Projection>,
540 from_clause: FromClause,
541 selection: Option<Selection>,
542 group_by: Vec<GroupByParameter>,
543 order_by: Vec<OrderByParameter>,
544 },
545 Insert {
546 table: String,
547 columns: Vec<String>,
548 source: Vec<Vec<InsertSource>>,
549 },
550 Update {
551 table: String,
552 assignments: Vec<UpdateAssignment>,
553 selection: Option<Selection>,
554 },
555 Delete {
556 from_clause: FromClause,
557 selection: Option<Selection>,
558 },
559 DropTable {
560 if_exists: bool,
561 name: String,
562 },
563 DropIndex {
564 if_exists: bool,
565 name: String,
566 table: String,
567 },
568}
569
570#[derive(Debug, Clone, PartialEq)]
571pub enum Projection {
572 WildCard,
573 Identifier(String),
574 CompoundIdentifier(CompoundIdentifier),
575 Function(Function),
576 NumericLiteral(String),
577 String(String),
578}
579
580#[derive(Debug, Clone, PartialEq)]
581pub struct CompoundIdentifier {
582 table: String,
583 column: String,
584}
585
586#[derive(Debug, Clone, PartialEq)]
587pub enum Function {
588 Count(FunctionArg),
589}
590
591#[derive(Debug, Clone, PartialEq)]
592pub enum FunctionArg {
593 Wildcard,
594 Ident(String),
595}
596
597#[derive(Debug, Clone, PartialEq)]
598pub enum Selection {
599 BinaryOp {
600 op: Op,
601 left: Box<Selection>,
602 right: Box<Selection>,
603 },
604 Ident(String),
605 CompoundIdentifier(CompoundIdentifier),
606 Number(String),
607 String(String),
608 Placeholder,
609 InList {
610 negated: bool,
611 ident: String,
612 list: Vec<Selection>,
613 },
614}
615
616impl TryFrom<&Expr> for Selection {
617 type Error = Error;
618
619 fn try_from(expr: &Expr) -> std::result::Result<Self, Self::Error> {
620 let selection = match expr {
621 Expr::BinaryOp { left, op, right } => Selection::BinaryOp {
622 op: op.try_into()?,
623 left: {
624 let left: Selection = left.as_ref().try_into()?;
625 Box::new(left)
626 },
627 right: {
628 let right: Selection = right.as_ref().try_into()?;
629 Box::new(right)
630 },
631 },
632 Expr::Identifier(id) => Selection::Ident(id.value.clone()),
633 Expr::CompoundIdentifier(ids) => {
634 if ids.len() != 2 {
636 Err(Error::CompoundIdentifier { length: ids.len() })?
637 }
638 Selection::CompoundIdentifier(CompoundIdentifier {
639 table: ids[0].value.clone(),
640 column: ids[1].value.clone(),
641 })
642 }
643 Expr::Value(value) => match &value.value {
644 Value::Number(number, _) => Selection::Number(number.clone()),
645 Value::SingleQuotedString(string) => Selection::String(string.clone()),
646 Value::Placeholder(_) => Selection::Placeholder,
647 _ => Err(Error::SelectionValue {
648 value: Box::new(value.value.clone()),
649 })?,
650 },
651 Expr::InList {
652 expr,
653 list,
654 negated,
655 } => {
656 let ident = match expr.as_ref().try_into()? {
657 Selection::Ident(ident) => ident,
658 selection => Err(Error::SelectionInList {
659 selection: Box::new(selection.clone()),
660 })?,
661 };
662 let list = list
663 .iter()
664 .map(|expr| {
665 let ok = match expr.try_into()? {
666 ok @ Selection::String(_) => ok,
667 ok @ Selection::Number(_) => ok,
668 ok @ Selection::Placeholder => ok,
669 selection => Err(Error::SelectionInList {
670 selection: Box::new(selection.clone()),
671 })?,
672 };
673 Ok(ok)
674 })
675 .collect::<Result<Vec<Selection>>>()?;
676 Selection::InList {
677 negated: *negated,
678 ident,
679 list,
680 }
681 }
682 expr => Err(Error::SelectionFromExpr {
683 expr: Box::new(expr.clone()),
684 })?,
685 };
686 Ok(selection)
687 }
688}
689
690#[derive(Debug, Clone, PartialEq)]
691pub enum GroupByParameter {
692 Ident(String),
693}
694
695#[derive(Debug, Clone, PartialEq)]
696pub struct OrderByParameter {
697 ident: String,
698 option: OrderOption,
699}
700
701#[derive(Debug, Clone, PartialEq)]
702pub enum OrderOption {
703 Asc,
704 Desc,
705 None,
706}
707
708#[derive(Debug, Clone, PartialEq)]
709pub enum InsertSource {
710 String(String),
711 Number(String),
712 Null,
713 Placeholder,
714 Cast {
715 cast: String,
716 source: Box<InsertSource>,
717 },
718}
719
720impl TryFrom<&Expr> for InsertSource {
721 type Error = Error;
722
723 fn try_from(value: &Expr) -> Result<Self, Self::Error> {
724 let value = match value {
725 Expr::Value(value) => &value.value,
726 Expr::Cast {
727 kind,
728 expr,
729 data_type,
730 format,
731 } if *kind == CastKind::DoubleColon && format.is_none() => match expr.as_ref() {
732 Expr::Value(_) => {
733 return Ok(InsertSource::Cast {
734 cast: data_type.to_string(),
735 source: Box::new(expr.as_ref().try_into()?),
736 });
737 }
738 _ => Err(Error::InsertSourceExpression { expr: expr.clone() })?,
739 },
740 value => Err(Error::InsertSourceExpression {
741 expr: Box::new(value.clone()),
742 })?,
743 };
744 let insert_source = match value {
745 Value::Null => InsertSource::Null,
746 Value::Number(number, _) => InsertSource::Number(number.clone()),
747 Value::SingleQuotedString(string) => InsertSource::String(string.clone()),
748 Value::Placeholder(_) => InsertSource::Placeholder,
749 value => Err(Error::InsertSourceValue {
750 value: Box::new(value.clone()),
751 })?,
752 };
753 Ok(insert_source)
754 }
755}
756
757#[derive(Debug, Clone, PartialEq)]
758pub struct UpdateAssignment {
759 target: String,
760 value: UpdateValue,
761}
762
763#[derive(Debug, Clone, PartialEq)]
764pub enum UpdateValue {
765 String(String),
766 Number(String),
767 Null,
768 Placeholder,
769}
770
771impl TryFrom<&Expr> for UpdateValue {
772 type Error = Error;
773
774 fn try_from(expr: &Expr) -> Result<Self, Self::Error> {
775 let value = match expr {
776 Expr::Value(value) => &value.value,
777 expr => Err(Error::UpdateExpression {
778 expr: Box::new(expr.clone()),
779 })?,
780 };
781 let update_value = match value {
782 Value::Null => UpdateValue::Null,
783 Value::Number(number, _) => UpdateValue::Number(number.clone()),
784 Value::SingleQuotedString(string) => UpdateValue::String(string.clone()),
785 Value::Placeholder(_) => UpdateValue::Placeholder,
786 value => Err(Error::UpdateValue {
787 value: Box::new(value.clone()),
788 })?,
789 };
790 Ok(update_value)
791 }
792}
793
794#[derive(Debug, Clone, Copy, PartialEq)]
795pub enum Op {
796 Eq,
797 And,
798 Or,
799}
800
801impl TryFrom<&BinaryOperator> for Op {
802 type Error = Error;
803
804 fn try_from(op: &BinaryOperator) -> std::result::Result<Self, Self::Error> {
805 let op = match op {
806 BinaryOperator::And => Op::And,
807 BinaryOperator::Eq => Op::Eq,
808 BinaryOperator::Or => Op::Or,
809 _ => Err(Error::BinaryOperator { op: op.clone() })?,
810 };
811 Ok(op)
812 }
813}
814
815#[derive(Debug, Clone, PartialEq)]
816pub enum FromClause {
817 Table(String),
818 TableWithJoin(TableJoin),
819 None,
820}
821
822#[derive(Debug, Clone, PartialEq)]
823pub struct TableJoin {
824 name: String,
825 join: Vec<Join>,
826}
827
828#[derive(Debug, Clone, PartialEq)]
829pub struct Join {
830 name: String,
831 operator: JoinOperator,
832}
833
834#[derive(Debug, Clone, PartialEq)]
835pub enum JoinOperator {
836 Join(Selection),
837 Inner(Selection),
838}
839
840impl TryFrom<&sqlparser::ast::Join> for Join {
841 type Error = Error;
842
843 fn try_from(table: &sqlparser::ast::Join) -> Result<Self, Self::Error> {
844 if table.global {
847 Err(Error::Keyword { keyword: "GLOBAL" })?
848 };
849
850 let name = table_relation_to_object_name(&table.relation)?;
851 let operator = match &table.join_operator {
852 sqlparser::ast::JoinOperator::Join(constraint) => match constraint {
853 JoinConstraint::On(expr) => JoinOperator::Join(expr.try_into()?),
854 other => Err(Error::JoinConstraint {
855 constraint: Box::new(other.clone()),
856 })?,
857 },
858 sqlparser::ast::JoinOperator::Inner(constraint) => match constraint {
859 JoinConstraint::On(expr) => JoinOperator::Inner(expr.try_into()?),
860 other => Err(Error::JoinConstraint {
861 constraint: Box::new(other.clone()),
862 })?,
863 },
864 other => Err(Error::JoinOperator {
865 op: Box::new(other.clone()),
866 })?,
867 };
868
869 Ok(Self { name, operator })
870 }
871}
872
873fn table_relation_to_object_name(relation: &TableFactor) -> Result<String> {
874 match relation {
875 TableFactor::Table {
876 name,
877 alias,
878 args,
879 with_hints,
880 version,
881 with_ordinality,
882 partitions,
883 json_path,
884 sample,
885 index_hints,
886 } => {
887 if alias.is_some() {
888 Err(Error::TableAlias)?
889 }
890 if args.is_some() {
891 Err(Error::TableValuedFunctions)?
892 }
893 if !with_hints.is_empty() {
894 Err(Error::TableWithHints)?
895 }
896 if version.is_some() {
897 Err(Error::TableVersioning)?
898 }
899 if *with_ordinality {
900 Err(Error::TableWithOrdinality)?
901 }
902 if !partitions.is_empty() {
903 Err(Error::TableWithPartitions)?
904 }
905 if json_path.is_some() {
906 Err(Error::TableWithJsonPath)?
907 }
908 if sample.is_some() {
909 Err(Error::TableWithSampleModifier)?
910 }
911 if !index_hints.is_empty() {
912 Err(Error::TableWithIndexHints)?
913 }
914 Ok(Ast::parse_object_name(name)?)
915 }
916 other => Err(Error::TableFactor {
917 factor: Box::new(other.clone()),
918 })?,
919 }
920}
921
922impl TryFrom<&[TableWithJoins]> for FromClause {
923 type Error = Error;
924
925 fn try_from(tables: &[TableWithJoins]) -> Result<Self, Self::Error> {
926 let from = match tables {
927 &[
928 TableWithJoins {
929 ref relation,
930 ref joins,
931 },
932 ] => {
933 let name = table_relation_to_object_name(relation)?;
934 if joins.is_empty() {
935 Self::Table(name)
936 } else {
937 Self::TableWithJoin(TableJoin {
938 name,
939 join: joins.iter().map(|t| t.try_into()).collect::<Result<_>>()?,
940 })
941 }
942 }
943 &[] => Self::None,
944 other => Err(Error::TableJoins {
945 table_joins: other.iter().map(Clone::clone).collect(),
946 })?,
947 };
948 Ok(from)
949 }
950}
951
952#[derive(Debug, Clone, PartialEq)]
953pub enum AlterTableOperation {
954 AddColumn { column: Column },
955 RenameColumn { from: String, to: String },
956 DropColumn { name: String },
957 RenameTable { to: String },
958}
959
960impl TryFrom<&sqlparser::ast::AlterTableOperation> for AlterTableOperation {
961 type Error = Error;
962
963 fn try_from(
964 op: &sqlparser::ast::AlterTableOperation,
965 ) -> std::result::Result<Self, Self::Error> {
966 let op = match op {
967 sqlparser::ast::AlterTableOperation::AddColumn {
968 column_keyword,
969 if_not_exists,
970 column_def,
971 column_position,
972 } => {
973 let _ = column_keyword;
974 if *if_not_exists {
975 Err(Error::AlterTable {
976 reason: "if not exists",
977 })?
978 }
979 if column_position.is_some() {
980 Err(Error::AlterTable {
981 reason: "column position",
982 })?
983 }
984 let column = column_def.try_into()?;
985 AlterTableOperation::AddColumn { column }
986 }
987 sqlparser::ast::AlterTableOperation::RenameTable { table_name } => {
988 let table_name = match table_name {
989 sqlparser::ast::RenameTableNameKind::As(_) => Err(Error::AlterTable {
991 reason: "as keyword",
992 })?,
993 sqlparser::ast::RenameTableNameKind::To(table_name) => table_name,
994 };
995 AlterTableOperation::RenameTable {
996 to: Ast::parse_object_name(table_name)?,
997 }
998 }
999 sqlparser::ast::AlterTableOperation::RenameColumn {
1000 old_column_name,
1001 new_column_name,
1002 } => AlterTableOperation::RenameColumn {
1003 from: old_column_name.value.clone(),
1004 to: new_column_name.value.clone(),
1005 },
1006 sqlparser::ast::AlterTableOperation::DropColumn {
1007 if_exists,
1008 drop_behavior,
1009 has_column_keyword,
1010 column_names,
1011 } => {
1012 if *if_exists {
1013 Err(Error::AlterTable {
1014 reason: "if exists",
1015 })?
1016 }
1017 if drop_behavior.is_some() {
1018 Err(Error::AlterTable {
1019 reason: "drop behaviour",
1020 })?;
1021 }
1022 if column_names.len() > 1 {
1023 Err(Error::AlterTable {
1024 reason: "multiple columns names",
1025 })?
1026 }
1027 AlterTableOperation::DropColumn {
1028 name: column_names.first().unwrap().value.clone(),
1029 }
1030 }
1031 op => Err(Error::AlterTableOp {
1032 op: Box::new(op.clone()),
1033 })?,
1034 };
1035 Ok(op)
1036 }
1037}
1038
1039impl Ast {
1040 fn parse_object_name(name: &ObjectName) -> Result<String> {
1041 let name_parts = &name.0;
1042 if name_parts.len() > 1 {
1043 Err(Error::ObjectName {
1044 reason: "schema-qualified names are not supported",
1045 })?
1046 }
1047 match name_parts.first() {
1048 None => Err(Error::ObjectName {
1049 reason: "name parts are empty",
1050 })?,
1051 Some(ObjectNamePart::Identifier(ident)) => Ok(ident.value.clone()),
1052 Some(ObjectNamePart::Function(_)) => Err(Error::ObjectName {
1053 reason: "function names are not supported",
1054 })?,
1055 }
1056 }
1057
1058 fn parse_create_table(
1059 SqlParserCreateTable {
1060 or_replace,
1061 temporary,
1062 external,
1063 global,
1064 if_not_exists,
1065 transient,
1066 volatile,
1067 iceberg,
1068 name,
1069 columns,
1070 constraints,
1071 hive_distribution,
1072 hive_formats,
1073 file_format,
1074 location,
1075 query,
1076 without_rowid,
1077 like,
1078 clone,
1079 comment,
1080 on_commit,
1081 on_cluster,
1082 primary_key,
1083 order_by,
1084 partition_by,
1085 cluster_by,
1086 clustered_by,
1087 inherits,
1088 strict,
1089 copy_grants,
1090 enable_schema_evolution,
1091 change_tracking,
1092 data_retention_time_in_days,
1093 max_data_extension_time_in_days,
1094 default_ddl_collation,
1095 with_aggregation_policy,
1096 with_row_access_policy,
1097 with_tags,
1098 external_volume,
1099 base_location,
1100 catalog,
1101 catalog_sync,
1102 storage_serialization_policy,
1103 dynamic,
1104 table_options,
1105 version,
1106 target_lag,
1107 warehouse,
1108 refresh_mode,
1109 initialize,
1110 require_user,
1111 }: &SqlParserCreateTable,
1112 ) -> Result<Ast> {
1113 if *or_replace {
1114 Err(Error::CreateTable {
1115 reason: "or replace",
1116 })?
1117 }
1118 if *temporary {
1119 Err(Error::CreateTable {
1120 reason: "temporary",
1121 })?
1122 }
1123 if *external {
1124 Err(Error::CreateTable { reason: "external" })?
1125 }
1126 if global.is_some() {
1127 Err(Error::CreateTable { reason: "global" })?
1128 }
1129 if *transient {
1130 Err(Error::CreateTable {
1131 reason: "transient",
1132 })?
1133 }
1134 if *volatile {
1135 Err(Error::CreateTable { reason: "volatile" })?
1136 }
1137 if *iceberg {
1138 Err(Error::CreateTable { reason: "iceberg" })?
1139 }
1140 match hive_distribution {
1141 HiveDistributionStyle::NONE => {}
1142 _ => Err(Error::CreateTable {
1143 reason: "hive distribution style",
1144 })?,
1145 }
1146
1147 if let Some(HiveFormat {
1149 row_format,
1150 serde_properties,
1151 storage,
1152 location,
1153 }) = hive_formats
1154 && (row_format.is_some()
1155 || serde_properties.is_some()
1156 || storage.is_some()
1157 || location.is_some())
1158 {
1159 Err(Error::CreateTable {
1160 reason: "hive formats",
1161 })?
1162 }
1163
1164 if file_format.is_some() {
1165 Err(Error::CreateTable {
1166 reason: "file format",
1167 })?
1168 }
1169 if location.is_some() {
1170 Err(Error::CreateTable { reason: "location" })?
1171 }
1172 if query.is_some() {
1173 Err(Error::CreateTable { reason: "query" })?
1174 }
1175 if *without_rowid {
1176 Err(Error::CreateTable {
1177 reason: "without rowid",
1178 })?
1179 }
1180 if like.is_some() {
1181 Err(Error::CreateTable { reason: "like" })?
1182 }
1183 if clone.is_some() {
1184 Err(Error::CreateTable { reason: "clone" })?
1185 }
1186 if comment.is_some() {
1187 Err(Error::CreateTable { reason: "comment" })?
1188 }
1189 if on_commit.is_some() {
1190 Err(Error::CreateTable {
1191 reason: "on commit",
1192 })?
1193 }
1194 if on_cluster.is_some() {
1196 Err(Error::CreateTable {
1197 reason: "on cluster",
1198 })?
1199 }
1200 if primary_key.is_some() {
1202 Err(Error::CreateTable {
1203 reason: "primary key",
1204 })?
1205 }
1206 if order_by.is_some() {
1208 Err(Error::CreateTable { reason: "order by" })?
1209 }
1210 if partition_by.is_some() {
1212 Err(Error::CreateTable {
1213 reason: "partition by",
1214 })?
1215 }
1216 if cluster_by.is_some() {
1218 Err(Error::CreateTable {
1219 reason: "cluster by",
1220 })?
1221 }
1222 if clustered_by.is_some() {
1224 Err(Error::CreateTable {
1225 reason: "clustered by",
1226 })?
1227 }
1228 if inherits.is_some() {
1230 Err(Error::CreateTable { reason: "inherits" })?
1231 }
1232 if *strict {
1234 Err(Error::CreateTable { reason: "strict" })?
1235 }
1236 if *copy_grants {
1238 Err(Error::CreateTable {
1239 reason: "copy grant",
1240 })?
1241 }
1242 if enable_schema_evolution.is_some() {
1244 Err(Error::CreateTable {
1245 reason: "enable schema evolution",
1246 })?
1247 }
1248 if change_tracking.is_some() {
1250 Err(Error::CreateTable {
1251 reason: "change tracking",
1252 })?
1253 }
1254 if data_retention_time_in_days.is_some() {
1256 Err(Error::CreateTable {
1257 reason: "data retention time in days",
1258 })?
1259 }
1260 if max_data_extension_time_in_days.is_some() {
1262 Err(Error::CreateTable {
1263 reason: "max data extension time in days",
1264 })?
1265 }
1266 if default_ddl_collation.is_some() {
1268 Err(Error::CreateTable {
1269 reason: "default ddl collation",
1270 })?
1271 }
1272 if with_aggregation_policy.is_some() {
1274 Err(Error::CreateTable {
1275 reason: "with aggragation policy",
1276 })?
1277 }
1278 if with_row_access_policy.is_some() {
1280 Err(Error::CreateTable {
1281 reason: "with row access policy",
1282 })?
1283 }
1284 if with_tags.is_some() {
1286 Err(Error::CreateTable {
1287 reason: "with tags",
1288 })?
1289 }
1290 if external_volume.is_some() {
1292 Err(Error::CreateTable {
1293 reason: "external volume",
1294 })?
1295 }
1296 if base_location.is_some() {
1298 Err(Error::CreateTable {
1299 reason: "base location",
1300 })?
1301 }
1302 if catalog.is_some() {
1304 Err(Error::CreateTable { reason: "catalog" })?
1305 }
1306 if catalog_sync.is_some() {
1308 Err(Error::CreateTable {
1309 reason: "catalog sync",
1310 })?
1311 }
1312 if storage_serialization_policy.is_some() {
1314 Err(Error::CreateTable {
1315 reason: "storage serialization policy",
1316 })?
1317 }
1318 if *dynamic {
1319 Err(Error::CreateTable { reason: "dynamic" })?
1320 }
1321 match table_options {
1322 CreateTableOptions::None => (),
1323 _ => Err(Error::CreateTable {
1324 reason: "table options",
1325 })?,
1326 };
1327
1328 if version.is_some() {
1329 Err(Error::CreateTable { reason: "versions" })?
1330 }
1331
1332 if target_lag.is_some() {
1334 Err(Error::CreateTable {
1335 reason: "target lag",
1336 })?
1337 }
1338 if warehouse.is_some() {
1340 Err(Error::CreateTable {
1341 reason: "warehouse",
1342 })?
1343 }
1344 if refresh_mode.is_some() {
1346 Err(Error::CreateTable {
1347 reason: "refresh mode",
1348 })?
1349 }
1350 if initialize.is_some() {
1352 Err(Error::CreateTable {
1353 reason: "initialize",
1354 })?
1355 }
1356 if *require_user {
1358 Err(Error::CreateTable {
1359 reason: "require user",
1360 })?
1361 }
1362
1363 let name = Self::parse_object_name(name)?;
1364 let columns = {
1365 columns
1366 .iter()
1367 .map(TryFrom::try_from)
1368 .collect::<Result<Vec<_>>>()?
1369 };
1370 Ok(Ast::CreateTable {
1371 if_not_exists: *if_not_exists,
1372 name,
1373 columns,
1374 constraints: Constraints::try_from(constraints.as_slice())?,
1375 })
1376 }
1377
1378 #[allow(clippy::too_many_arguments)]
1379 fn parse_alter_table(
1380 name: &ObjectName,
1381 if_exists: bool,
1382 only: bool,
1383 operations: &[sqlparser::ast::AlterTableOperation],
1384 location: Option<&sqlparser::ast::HiveSetLocation>,
1385 on_cluster: Option<&Ident>,
1386 iceberg: bool,
1387 _end_token: &sqlparser::ast::helpers::attached_token::AttachedToken,
1388 ) -> Result<Ast> {
1389 if if_exists {
1391 Err(Error::AlterTable {
1392 reason: "if exists",
1393 })?
1394 }
1395 if only {
1397 Err(Error::AlterTable { reason: "on" })?
1398 }
1399 if on_cluster.is_some() {
1401 Err(Error::AlterTable {
1402 reason: "on cluster",
1403 })?
1404 }
1405 if location.is_some() {
1407 Err(Error::AlterTable { reason: "location" })?
1408 }
1409 if iceberg {
1411 Err(Error::AlterTable { reason: "iceberg" })?
1412 }
1413 let name = Self::parse_object_name(name)?;
1414 if operations.len() != 1 {
1415 Err(Error::AlterTable {
1416 reason: "only supports single operation",
1417 })?
1418 }
1419 let operation = operations.first().unwrap().try_into()?;
1420 Ok(Ast::AlterTable { name, operation })
1421 }
1422
1423 fn parse_function_args(args: &FunctionArguments) -> Result<Vec<FunctionArg>> {
1424 let args = match args {
1425 FunctionArguments::None => vec![],
1426 FunctionArguments::List(list) => {
1427 if !list.clauses.is_empty() {
1428 Err(Error::FunctionArguments {
1429 reason: "function clauses are not yet supported",
1430 arguments: Box::new(args.clone()),
1431 })?
1432 };
1433 if list.duplicate_treatment.is_some() {
1434 Err(Error::FunctionArguments {
1435 reason: "function duplicate treatment not supported",
1436 arguments: Box::new(args.clone()),
1437 })?
1438 }
1439 list.args
1440 .iter()
1441 .map(|arg| -> Result<_> {
1442 let arg = match arg {
1444 sqlparser::ast::FunctionArg::ExprNamed { .. } => {
1445 Err(Error::FunctionArgument {
1446 reason: "named expressions",
1447 argument: Box::new(arg.clone()),
1448 })?
1449 }
1450 sqlparser::ast::FunctionArg::Named { .. } => {
1451 Err(Error::FunctionArgument {
1452 reason: "named columns",
1453 argument: Box::new(arg.clone()),
1454 })?
1455 }
1456 sqlparser::ast::FunctionArg::Unnamed(expr) => match expr {
1457 sqlparser::ast::FunctionArgExpr::Wildcard => FunctionArg::Wildcard,
1458 sqlparser::ast::FunctionArgExpr::Expr(Expr::Identifier(ident)) => {
1459 FunctionArg::Ident(ident.value.clone())
1460 }
1461 _ => Err(Error::FunctionArgument {
1462 reason: "unnamed",
1463 argument: Box::new(arg.clone()),
1464 })?,
1465 },
1466 };
1467 Ok(arg)
1468 })
1469 .collect::<Result<_>>()?
1470 }
1471 FunctionArguments::Subquery(query) => Err(Error::FunctionArguments {
1472 reason: "subquery",
1473 arguments: Box::new(args.clone()),
1474 })?,
1475 };
1476 Ok(args)
1477 }
1478
1479 fn parse_create_index(
1480 CreateIndex {
1481 name,
1482 table_name,
1483 columns,
1484 if_not_exists,
1485 unique,
1486 concurrently,
1487 using,
1488 include,
1489 nulls_distinct,
1490 with,
1491 predicate,
1492 index_options,
1493 alter_options,
1494 }: &CreateIndex,
1495 ) -> Result<Self> {
1496 if *if_not_exists {
1497 Err(Error::CreateIndex {
1498 reason: "existance check",
1499 })?
1500 };
1501 if name.is_none() {
1502 Err(Error::CreateIndex { reason: "nameless" })?
1503 }
1504 if *concurrently {
1505 Err(Error::CreateIndex {
1506 reason: "concurrent",
1507 })?
1508 }
1509 if using.is_some() {
1510 Err(Error::CreateIndex { reason: "using" })?
1511 }
1512 if !include.is_empty() {
1513 Err(Error::CreateIndex { reason: "include" })?
1514 }
1515 if nulls_distinct.is_some() {
1516 Err(Error::CreateIndex {
1517 reason: "distinct nulls",
1518 })?
1519 }
1520 if !with.is_empty() {
1521 Err(Error::CreateIndex { reason: "with" })?
1522 }
1523 if predicate.is_some() {
1524 Err(Error::CreateIndex {
1525 reason: "predicate",
1526 })?
1527 }
1528 if !index_options.is_empty() {
1530 Err(Error::CreateIndex {
1531 reason: "index options",
1532 })?
1533 }
1534 if !alter_options.is_empty() {
1536 Err(Error::CreateIndex {
1537 reason: "alter options",
1538 })?
1539 }
1540 let columns = columns
1541 .iter()
1542 .map(
1543 |index_column @ IndexColumn { column, .. }| -> Result<String> {
1544 match &column.expr {
1545 Expr::Identifier(Ident { value, .. }) => Ok(value.clone()),
1546 expr => Err(Error::CreateIndexColumn {
1547 column: Box::new(index_column.clone()),
1548 })?,
1549 }
1550 },
1551 )
1552 .collect::<Result<Vec<String>>>()?;
1553 Ok(Ast::CreateIndex {
1554 unique: *unique,
1555 name: Self::parse_object_name(name.as_ref().unwrap())?,
1556 table: Self::parse_object_name(table_name)?,
1557 columns,
1558 })
1559 }
1560
1561 fn parse_query(query: &Query) -> Result<Ast> {
1562 if query.with.is_some() {
1564 Err(Error::CTE)?
1565 }
1566 if query.fetch.is_some() {
1567 Err(Error::Fetch)?
1568 }
1569 if query.limit_clause.is_some() {
1571 Err(Error::Limit)?
1572 }
1573 if !query.locks.is_empty() {
1574 Err(Error::Locks)?
1575 }
1576 if query.for_clause.is_some() {
1577 Err(Error::For)?
1578 }
1579 let select = match &*query.body {
1580 SetExpr::Select(select) => &**select,
1581 other => Err(Error::Select {
1582 set_expr: Box::new(other.clone()),
1583 })?,
1584 };
1585 if select.top.is_some() || select.top_before_distinct {
1586 Err(Error::Top)?;
1587 }
1588 if select.projection.is_empty() {
1589 Err(Error::EmptyProjections)?;
1590 }
1591 let projections = select
1592 .projection
1593 .iter()
1594 .map(|projection| -> Result<_> {
1595 match projection {
1596 SelectItem::Wildcard(_) => Ok(Projection::WildCard),
1597 SelectItem::UnnamedExpr(Expr::Identifier(ident)) => {
1598 Ok(Projection::Identifier(ident.value.clone()))
1599 }
1600 SelectItem::UnnamedExpr(Expr::Function(function)) => {
1601 let function_name = Self::parse_object_name(&function.name)?.to_lowercase();
1602 match function_name.as_str() {
1603 "count" => {
1604 let mut args = Self::parse_function_args(&function.args)?;
1605 if args.len() != 1 {
1606 Err(Error::Count {
1607 reason: "function can only have single argument",
1608 args: args.clone(),
1609 })?
1610 }
1611 let arg = args.pop().unwrap();
1612 Ok(Projection::Function(Function::Count(arg)))
1613 }
1614 name => Err(Error::Function {
1615 name: function_name,
1616 })?,
1617 }
1618 }
1619 SelectItem::UnnamedExpr(Expr::Value(value)) => match &value.value {
1620 Value::Number(value, _) => Ok(Projection::NumericLiteral(value.clone())),
1621 Value::SingleQuotedString(value) => Ok(Projection::String(value.clone())),
1622 value => Err(Error::SelectionValue {
1623 value: Box::new(value.clone()),
1624 })?,
1625 },
1626 SelectItem::UnnamedExpr(Expr::CompoundIdentifier(values)) => {
1627 if values.len() != 2 {
1629 Err(Error::CompoundIdentifier {
1630 length: values.len(),
1631 })?
1632 }
1633 Ok(Projection::CompoundIdentifier(CompoundIdentifier {
1634 table: values[0].value.clone(),
1635 column: values[1].value.clone(),
1636 }))
1637 }
1638 _ => Err(Error::Projection {
1639 select_item: Box::new(projection.clone()),
1640 })?,
1641 }
1642 })
1643 .collect::<Result<Vec<Projection>>>()?;
1644
1645 let from_clause = select.from.as_slice().try_into()?;
1646
1647 let selection = select
1648 .selection
1649 .as_ref()
1650 .map(|selection| selection.try_into())
1651 .transpose()?;
1652 let group_by = match &select.group_by {
1653 sqlparser::ast::GroupByExpr::Expressions(expr, modifier) if modifier.is_empty() => expr
1654 .iter()
1655 .map(|expr| match expr {
1656 Expr::Identifier(ident) => Ok(GroupByParameter::Ident(ident.value.clone())),
1657 _ => Err(Error::GroupBy {
1658 reason: "unsupported expression in group by",
1659 })?,
1660 })
1661 .collect::<Result<Vec<GroupByParameter>>>()?,
1662 expr => Err(Error::GroupBy {
1663 reason: "unsupported group by expression",
1664 })?,
1665 };
1666 let order_by = match query.order_by.as_ref() {
1667 Some(order_by) => {
1668 if order_by.interpolate.is_some() {
1669 Err(Error::OrderBy {
1670 reason: "order by interpolate is not supported",
1671 })?;
1672 };
1673 match &order_by.kind {
1674 sqlparser::ast::OrderByKind::All(_) => Err(Error::OrderBy {
1675 reason: "order by all is not supported",
1676 })?,
1677 sqlparser::ast::OrderByKind::Expressions(expressions) => expressions
1678 .iter()
1679 .map(|expression| {
1680 if expression.with_fill.is_some() {
1681 Err(Error::OrderBy {
1682 reason: "with fill is not supported",
1683 })?
1684 }
1685 let ident = match &expression.expr {
1686 Expr::Identifier(ident) => ident.value.clone(),
1687 expr => Err(Error::OrderBy {
1688 reason: "unsupported order by expression",
1689 })?,
1690 };
1691 let option = match &expression.options {
1692 sqlparser::ast::OrderByOptions { nulls_first, .. }
1693 if nulls_first.is_some() =>
1694 {
1695 Err(Error::OrderBy {
1696 reason: "order by with nulls first not supported",
1697 })?
1698 }
1699 sqlparser::ast::OrderByOptions { asc, .. } => match asc {
1700 None => OrderOption::None,
1701 Some(true) => OrderOption::Asc,
1702 Some(false) => OrderOption::Desc,
1703 },
1704 };
1705 Ok(OrderByParameter { ident, option })
1706 })
1707 .collect::<Result<Vec<_>>>()?,
1708 }
1709 }
1710 None => vec![],
1711 };
1712 let ast = Ast::Select {
1713 distinct: select.distinct.is_some(),
1714 projections,
1715 from_clause,
1716 selection,
1717 group_by,
1718 order_by,
1719 };
1720 Ok(ast)
1721 }
1722
1723 fn parse_insert(insert: &sqlparser::ast::Insert) -> Result<Ast> {
1724 let sqlparser::ast::Insert {
1725 or,
1726 ignore,
1727 into,
1728 table,
1729 table_alias,
1730 columns,
1731 overwrite,
1732 source,
1733 assignments,
1734 partitioned,
1735 after_columns,
1736 has_table_keyword,
1737 on,
1738 returning,
1739 replace_into,
1740 priority,
1741 insert_alias,
1742 settings,
1743 format_clause,
1744 } = insert;
1745 if or.is_some() {
1747 Err(Error::Insert { reason: "or" })?
1748 };
1749 if *ignore {
1751 Err(Error::Insert { reason: "ignore" })?
1752 }
1753 if !*into {
1754 Err(Error::Insert {
1755 reason: "missing into",
1756 })?
1757 }
1758 if table_alias.is_some() {
1759 Err(Error::Insert {
1760 reason: "table alias",
1761 })?
1762 }
1763 if *overwrite {
1764 Err(Error::Insert {
1765 reason: "overwrite",
1766 })?
1767 }
1768 if !assignments.is_empty() {
1769 Err(Error::Insert {
1770 reason: "assignments",
1771 })?
1772 }
1773 if partitioned.is_some() || !after_columns.is_empty() {
1774 Err(Error::Insert {
1775 reason: "partitioned",
1776 })?
1777 }
1778 if *has_table_keyword {
1779 Err(Error::Insert {
1780 reason: "table keyword",
1781 })?
1782 }
1783 if on.is_some() {
1785 Err(Error::Insert {
1786 reason: "on keyword",
1787 })?
1788 }
1789 if returning.is_some() {
1790 Err(Error::Insert {
1791 reason: "returning",
1792 })?
1793 }
1794 if *replace_into {
1795 Err(Error::Insert { reason: "replace" })?
1796 }
1797 if priority.is_some() {
1798 Err(Error::Insert { reason: "priority" })?
1799 }
1800 if insert_alias.is_some() {
1801 Err(Error::Insert {
1802 reason: "insert alias",
1803 })?
1804 }
1805 if settings.is_some() {
1806 Err(Error::Insert { reason: "settings" })?
1807 }
1808 if format_clause.is_some() {
1809 Err(Error::Insert {
1810 reason: "format clause",
1811 })?
1812 }
1813 let name = match &table {
1814 sqlparser::ast::TableObject::TableName(name) => Self::parse_object_name(name)?,
1815 _ => Err(Error::InsertTableObject)?,
1816 };
1817 let source = match source {
1818 Some(source) => source,
1819 None => Err(Error::InsertSourceEmpty)?,
1820 };
1821 Ok(Ast::Insert {
1822 table: name,
1823 columns: columns.iter().map(|ident| ident.value.clone()).collect(),
1824 source: Self::parse_insert_source(source)?,
1825 })
1826 }
1827
1828 fn parse_insert_source(values: &Query) -> Result<Vec<Vec<InsertSource>>> {
1829 let values = match values.body.as_ref() {
1830 SetExpr::Values(values) if !values.explicit_row => values
1831 .rows
1832 .iter()
1833 .map(|row| -> Result<Vec<InsertSource>> {
1834 row.iter()
1835 .map(|value| value.try_into())
1836 .collect::<Result<_>>()
1837 })
1838 .collect::<Result<_>>()?,
1839 other => Err(Error::InsertSource {
1840 set_expr: Box::new(other.clone()),
1841 })?,
1842 };
1843 Ok(values)
1844 }
1845
1846 fn parse_update(
1847 table: &TableWithJoins,
1848 assignments: &[Assignment],
1849 from: Option<&UpdateTableFromKind>,
1850 selection: Option<&Expr>,
1851 returning: Option<&[SelectItem]>,
1852 or: Option<&SqliteOnConflict>,
1853 limit: Option<&Expr>,
1854 ) -> Result<Ast> {
1855 if from.is_some() {
1856 Err(Error::Update {
1857 reason: "from table",
1858 })?
1859 }
1860 if returning.is_some() {
1861 Err(Error::Update {
1862 reason: "returning",
1863 })?
1864 }
1865 if or.is_some() {
1866 Err(Error::Update {
1867 reason: "update with OR is not supported",
1868 })?
1869 }
1870 if limit.is_some() {
1871 Err(Error::Update {
1872 reason: "update with LIMIT is not supported",
1873 })?
1874 }
1875 let table = match &table.relation {
1876 TableFactor::Table { name, .. } => Self::parse_object_name(name)?,
1877 table_factor => Err(Error::UpdateTableType {
1878 table_factor: Box::new(table_factor.clone()),
1879 })?,
1880 };
1881 let assignments = assignments
1882 .iter()
1883 .map(|assigment| {
1884 let target = match &assigment.target {
1885 AssignmentTarget::ColumnName(name) => Self::parse_object_name(name)?,
1886 target => Err(Error::UpdateAssignmentTarget {
1887 target: Box::new(target.clone()),
1888 })?,
1889 };
1890 let value = (&assigment.value).try_into()?;
1891 Ok(UpdateAssignment { target, value })
1892 })
1893 .collect::<Result<Vec<UpdateAssignment>>>()?;
1894 let selection: Option<Selection> = selection
1895 .map(|selection| selection.try_into())
1896 .transpose()?;
1897 Ok(Ast::Update {
1898 table,
1899 assignments,
1900 selection,
1901 })
1902 }
1903
1904 fn parse_delete(delete: &Delete) -> Result<Ast> {
1905 if !delete.tables.is_empty() {
1906 Err(Error::Delete {
1907 reason: "multiple tables",
1908 })?
1909 }
1910 if delete.using.is_some() {
1911 Err(Error::Delete { reason: "using" })?
1912 }
1913 if delete.returning.is_some() {
1914 Err(Error::Delete {
1915 reason: "returning",
1916 })?
1917 }
1918 if !delete.order_by.is_empty() {
1919 Err(Error::Delete { reason: "order by" })?
1920 }
1921 if delete.limit.is_some() {
1922 Err(Error::Delete { reason: "limit" })?
1923 }
1924
1925 let tables = match &delete.from {
1926 FromTable::WithFromKeyword(tables) => tables,
1927 FromTable::WithoutKeyword(_) => Err(Error::Delete {
1928 reason: "without from",
1929 })?,
1930 };
1931 if tables.len() != 1 {
1932 Err(Error::Delete {
1933 reason: "multiple tables",
1934 })?
1935 }
1936
1937 let from_clause = tables.as_slice().try_into()?;
1938
1939 let selection = delete
1940 .selection
1941 .as_ref()
1942 .map(|selection| selection.try_into())
1943 .transpose()?;
1944 Ok(Ast::Delete {
1945 from_clause,
1946 selection,
1947 })
1948 }
1949
1950 fn parse_drop(
1951 object_type: &ObjectType,
1952 if_exists: bool,
1953 names: &[ObjectName],
1954 table: Option<&ObjectName>,
1955 ) -> Result<Self> {
1956 let name = match names {
1957 [table_name] => Self::parse_object_name(table_name)?,
1958 _ => Err(Error::Drop {
1959 reason: "multiple names",
1960 object_type: None,
1961 })?,
1962 };
1963 match object_type {
1964 ObjectType::Table => Ok(Ast::DropTable { if_exists, name }),
1965 ObjectType::Index => Self::parse_drop_index(if_exists, name, table),
1966 _ => Err(Error::Drop {
1967 reason: "object type",
1968 object_type: Some(*object_type),
1969 }),
1970 }
1971 }
1972
1973 fn parse_drop_index(if_exists: bool, name: String, table: Option<&ObjectName>) -> Result<Self> {
1974 let table = match table.map(Self::parse_object_name) {
1975 Some(name) => name?,
1976 None => Err(Error::DropIndex {
1977 reason: "table name required",
1978 })?,
1979 };
1980 Ok(Ast::DropIndex {
1981 if_exists,
1982 name,
1983 table,
1984 })
1985 }
1986
1987 pub fn parse(query: &str) -> Result<Vec<Ast>> {
1988 Parser::parse_sql(&dialect::GenericDialect {}, query)?
1989 .iter()
1990 .map(|statement| {
1991 let result = match statement {
1992 Statement::CreateTable(create_table) => Self::parse_create_table(create_table)?,
1993 Statement::AlterTable {
1994 name,
1995 if_exists,
1996 only,
1997 operations,
1998 location,
1999 on_cluster,
2000 iceberg,
2001 end_token,
2002 } => Self::parse_alter_table(
2003 name,
2004 *if_exists,
2005 *only,
2006 operations.as_slice(),
2007 location.as_ref(),
2008 on_cluster.as_ref(),
2009 *iceberg,
2010 end_token,
2011 )?,
2012 Statement::CreateIndex(index) => Self::parse_create_index(index)?,
2013 Statement::Query(query) => Self::parse_query(query)?,
2014 Statement::Drop {
2015 object_type,
2016 if_exists,
2017 names,
2018 cascade,
2019 restrict,
2020 purge,
2021 temporary,
2022 table,
2023 } => Self::parse_drop(object_type, *if_exists, names, table.as_ref())?,
2024 Statement::Insert(insert) => Self::parse_insert(insert)?,
2025 Statement::Update {
2026 table,
2027 assignments,
2028 from,
2029 selection,
2030 returning,
2031 or,
2032 limit,
2033 } => Self::parse_update(
2034 table,
2035 assignments.as_slice(),
2036 from.as_ref(),
2037 selection.as_ref(),
2038 returning.as_deref(),
2039 or.as_ref(),
2040 limit.as_ref(),
2041 )?,
2042 Statement::Delete(delete) => Self::parse_delete(delete)?,
2043 _ => Err(Error::Statement {
2044 statement: Box::new(statement.clone()),
2045 })?,
2046 };
2047 Ok(result)
2048 })
2049 .collect::<Result<Vec<_>>>()
2050 }
2051
2052 fn create_table_to_sql(
2053 dialect: &dyn ToQuery,
2054 buf: &mut dyn Write,
2055 if_not_exists: bool,
2056 name: &str,
2057 columns: &[Column],
2058 constraints: &Constraints,
2059 ) -> Result<()> {
2060 buf.write_all(b"CREATE TABLE ")?;
2061 if if_not_exists {
2062 buf.write_all(b"IF NOT EXISTS ")?;
2063 }
2064 Self::write_quoted(dialect, buf, name)?;
2065 buf.write_all(b" (\n")?;
2066 Self::table_columns_to_sql(dialect, buf, columns, "\n")?;
2067 if constraints.len() > 0 {
2068 buf.write_all(b",\n")?;
2069 }
2070 for (pos, constraint) in constraints.into_iter().enumerate() {
2071 match constraint {
2072 Constraint::PrimaryKey(fields) => {
2073 buf.write_all(b"PRIMARY KEY (")?;
2074 for (pos, field) in fields.iter().enumerate() {
2075 Self::write_quoted(dialect, buf, field)?;
2076 if pos != fields.len() - 1 {
2077 buf.write_all(b", ")?;
2078 }
2079 }
2080 buf.write_all(b")")?;
2081 }
2082 Constraint::ForeignKey {
2083 columns,
2084 referred_columns,
2085 foreign_table,
2086 on_delete,
2087 } => {
2088 buf.write_all(b"FOREIGN KEY (")?;
2089 for (pos, column) in columns.iter().enumerate() {
2090 Self::write_quoted(dialect, buf, column)?;
2091 if pos != columns.len() - 1 {
2092 buf.write_all(b", ")?;
2093 }
2094 }
2095 buf.write_all(b") REFERENCES ")?;
2096 buf.write_all(foreign_table.as_bytes());
2097 buf.write_all(b"(")?;
2098 for (pos, column) in referred_columns.iter().enumerate() {
2099 Self::write_quoted(dialect, buf, column)?;
2100 if pos != columns.len() - 1 {
2101 buf.write_all(b", ")?;
2102 }
2103 }
2104 buf.write_all(b")")?;
2105
2106 if let Some(delete_action) = on_delete {
2107 buf.write_all(b" ON DELETE ")?;
2108 match delete_action {
2109 OnDeleteAction::Cascade => buf.write_all(b"CASCADE")?,
2110 OnDeleteAction::SetNull => buf.write_all(b"SET NULL")?,
2111 OnDeleteAction::Restrict => buf.write_all(b"RESTRICT")?,
2112 }
2113 }
2114 }
2115 }
2116 if pos != constraints.len() - 1 {
2117 buf.write_all(b",\n")?;
2118 }
2119 }
2120 buf.write_all(b"\n)")?;
2121 Ok(())
2122 }
2123
2124 fn table_columns_to_sql(
2125 dialect: &dyn ToQuery,
2126 buf: &mut dyn Write,
2127 columns: &[Column],
2128 separator: &str,
2129 ) -> Result<()> {
2130 for (pos, column) in columns.iter().enumerate() {
2131 Self::write_quoted(dialect, buf, &column.name)?;
2132 buf.write_all(b" ")?;
2133
2134 dialect.emit_column_spec(column, buf)?;
2135 if pos != columns.len() - 1 {
2136 buf.write_all(b",")?;
2137 buf.write_all(separator.as_bytes())?;
2138 }
2139 }
2140 Ok(())
2141 }
2142
2143 fn create_index_to_sql(
2144 dialect: &dyn ToQuery,
2145 buf: &mut dyn Write,
2146 unique: bool,
2147 name: &str,
2148 table: &str,
2149 columns: &[String],
2150 ) -> Result<()> {
2151 if unique {
2152 buf.write_all(b"CREATE UNIQUE INDEX ")?;
2153 } else {
2154 buf.write_all(b"CREATE INDEX ")?;
2155 }
2156 Self::write_quoted(dialect, buf, name)?;
2157 buf.write_all(b" ON ")?;
2158 Self::write_quoted(dialect, buf, table)?;
2159 buf.write_all(b" (")?;
2160 for (pos, column) in columns.iter().enumerate() {
2161 Self::write_quoted(dialect, buf, column)?;
2162 if pos != columns.len() - 1 {
2163 buf.write_all(b", ")?;
2164 }
2165 }
2166 buf.write_all(b")")?;
2167 Ok(())
2168 }
2169
2170 #[allow(clippy::too_many_arguments)]
2171 fn select_to_sql(
2172 dialect: &dyn ToQuery,
2173 buf: &mut dyn Write,
2174 distinct: bool,
2175 projections: &[Projection],
2176 from_clause: &FromClause,
2177 selection: Option<&Selection>,
2178 group_by: &[GroupByParameter],
2179 order_by: &[OrderByParameter],
2180 ) -> Result<()> {
2181 buf.write_all(b"SELECT ")?;
2182 if distinct {
2183 buf.write_all(b"DISTINCT ")?;
2184 }
2185 for (pos, projection) in projections.iter().enumerate() {
2186 match projection {
2187 Projection::WildCard => buf.write_all(b"*")?,
2188 Projection::Identifier(ident) => {
2189 Self::write_quoted(dialect, buf, ident)?;
2190 }
2191 Projection::CompoundIdentifier(compound) => {
2192 Self::write_quoted(dialect, buf, &compound.table)?;
2193 buf.write_all(b".");
2194 Self::write_quoted(dialect, buf, &compound.column)?;
2195 }
2196 Projection::Function(function) => match function {
2197 Function::Count(FunctionArg::Wildcard) => buf.write_all(b"COUNT(*)")?,
2198 Function::Count(FunctionArg::Ident(ident)) => {
2199 buf.write_all(b"COUNT(")?;
2200 Self::write_quoted(dialect, buf, ident)?;
2201 buf.write_all(b")")?
2202 }
2203 },
2204 Projection::NumericLiteral(value) => buf.write_all(value.as_bytes())?,
2205 Projection::String(value) => Self::write_single_quoted(dialect, buf, value)?,
2206 };
2207 if pos != projections.len() - 1 {
2208 buf.write_all(b", ")?;
2209 }
2210 }
2211
2212 match from_clause {
2213 FromClause::Table(name) => {
2214 buf.write_all(b" FROM ")?;
2215 Self::write_quoted(dialect, buf, name)?
2216 }
2217 FromClause::None => (),
2218 FromClause::TableWithJoin(table) => {
2219 buf.write_all(b" FROM ")?;
2220 Self::write_quoted(dialect, buf, &table.name)?;
2221 for table in table.join.iter() {
2222 match &table.operator {
2223 JoinOperator::Join(selection) => {
2224 buf.write_all(b" JOIN ")?;
2225 Self::write_quoted(dialect, buf, &table.name);
2226 buf.write_all(b" ON ")?;
2227 Self::selection_to_sql(dialect, buf, selection)?;
2228 }
2229 JoinOperator::Inner(selection) => {
2230 buf.write_all(b" INNER JOIN ")?;
2231 Self::write_quoted(dialect, buf, &table.name);
2232 buf.write_all(b" ON ")?;
2233 Self::selection_to_sql(dialect, buf, selection)?;
2234 }
2235 }
2236 }
2237 }
2238 }
2239 if let Some(selection) = selection.as_ref() {
2240 buf.write_all(b" WHERE ")?;
2241 Self::selection_to_sql(dialect, buf, selection)?;
2242 };
2243
2244 if !group_by.is_empty() {
2245 buf.write_all(b" GROUP BY (")?;
2246 for (pos, parameter) in group_by.iter().enumerate() {
2247 match parameter {
2248 GroupByParameter::Ident(ident) => Self::write_quoted(dialect, buf, ident)?,
2249 }
2250 if pos != group_by.len() - 1 {
2251 buf.write_all(b", ")?;
2252 }
2253 }
2254 buf.write_all(b")")?;
2255 }
2256 if !order_by.is_empty() {
2257 buf.write_all(b" ORDER BY ")?;
2258 for (pos, order_option) in order_by.iter().enumerate() {
2259 Self::write_quoted(dialect, buf, order_option.ident.as_str())?;
2260 match &order_option.option {
2261 OrderOption::Asc => buf.write_all(b" ASC")?,
2262 OrderOption::Desc => buf.write_all(b" DESC")?,
2263 OrderOption::None => (),
2264 };
2265 if pos != order_by.len() - 1 {
2266 buf.write_all(b", ")?;
2267 }
2268 }
2269 }
2270 Ok(())
2271 }
2272
2273 fn insert_source_to_sql(
2274 dialect: &dyn ToQuery,
2275 buf: &mut dyn Write,
2276 insert_source: &InsertSource,
2277 place_holder_num: usize,
2278 ) -> Result<()> {
2279 match insert_source {
2280 InsertSource::Null => buf.write_all(b"NULL")?,
2281 InsertSource::Number(num) => buf.write_all(num.as_bytes())?,
2282 InsertSource::String(string) => Self::write_single_quoted(dialect, buf, string)?,
2283 InsertSource::Placeholder => {
2284 buf.write_all(dialect.placeholder(place_holder_num).as_bytes())?;
2285 }
2286 InsertSource::Cast { cast, source } => {
2287 Self::insert_source_to_sql(dialect, buf, source, place_holder_num)?;
2288 if dialect.placeholder_supports_cast() {
2289 buf.write_all(b"::")?;
2290 buf.write_all(cast.as_bytes())?;
2291 }
2292 }
2293 };
2294 Ok(())
2295 }
2296
2297 fn insert_to_sql(
2298 dialect: &dyn ToQuery,
2299 buf: &mut dyn Write,
2300 table: &str,
2301 columns: &[String],
2302 values: &[Vec<InsertSource>],
2303 ) -> Result<()> {
2304 buf.write_all(b"INSERT INTO ")?;
2305 Self::write_quoted(dialect, buf, table)?;
2306 if !columns.is_empty() {
2307 buf.write_all(b"(")?;
2308 for (pos, column) in columns.iter().enumerate() {
2309 if pos != 0 {
2310 buf.write_all(b", ")?;
2311 }
2312 Self::write_quoted(dialect, buf, column)?;
2313 }
2314 buf.write_all(b")")?;
2315 }
2316 buf.write_all(b" VALUES ")?;
2317 for (row_pos, row) in values.iter().enumerate() {
2318 if row_pos != 0 {
2319 buf.write_all(b", ")?;
2320 }
2321 buf.write_all(b"(")?;
2322 for (col_pos, insert_source) in row.iter().enumerate() {
2323 if col_pos != 0 {
2324 buf.write_all(b", ")?;
2325 }
2326 Self::insert_source_to_sql(
2327 dialect,
2328 buf,
2329 insert_source,
2330 row_pos * row.len() + col_pos + 1,
2331 )?;
2332 }
2333 buf.write_all(b")")?;
2334 }
2335 Ok(())
2336 }
2337
2338 fn selection_to_sql(
2339 dialect: &dyn ToQuery,
2340 buf: &mut dyn Write,
2341 selection: &Selection,
2342 ) -> Result<()> {
2343 let mut placeholder_count = 0;
2344 Self::selection_to_sql_with_placeholder_count(
2345 dialect,
2346 buf,
2347 selection,
2348 &mut placeholder_count,
2349 )
2350 }
2351
2352 fn selection_to_sql_with_placeholder_count(
2353 dialect: &dyn ToQuery,
2354 buf: &mut dyn Write,
2355 selection: &Selection,
2356 placeholder_count: &mut usize,
2357 ) -> Result<()> {
2358 match selection {
2359 Selection::BinaryOp { op, left, right } => {
2360 Self::selection_to_sql_with_placeholder_count(
2361 dialect,
2362 buf,
2363 left,
2364 placeholder_count,
2365 )?;
2366 match op {
2367 Op::And => buf.write_all(b" AND ")?,
2368 Op::Eq => buf.write_all(b" = ")?,
2369 Op::Or => buf.write_all(b" OR ")?,
2370 }
2371 Self::selection_to_sql_with_placeholder_count(
2372 dialect,
2373 buf,
2374 right,
2375 placeholder_count,
2376 )?;
2377 }
2378 Selection::Ident(ident) => Self::write_quoted(dialect, buf, ident)?,
2379 Selection::CompoundIdentifier(compound) => {
2380 Self::write_quoted(dialect, buf, &compound.table)?;
2381 buf.write_all(b".");
2382 Self::write_quoted(dialect, buf, &compound.column)?;
2383 }
2384 Selection::Number(number) => buf.write_all(number.as_bytes())?,
2385 Selection::String(string) => {
2386 for chunk in [b"'", string.as_bytes(), b"'"] {
2387 buf.write_all(chunk)?;
2388 }
2389 }
2390 Selection::Placeholder => {
2391 *placeholder_count += 1;
2392 buf.write_all(dialect.placeholder(*placeholder_count).as_bytes())?;
2393 }
2394 Selection::InList {
2395 negated,
2396 ident,
2397 list,
2398 } => {
2399 Self::write_quoted(dialect, buf, ident)?;
2400 if *negated {
2401 buf.write_all(b" NOT")?;
2402 }
2403 buf.write_all(b" IN ")?;
2404 buf.write_all(b"(")?;
2405 for (pos, selection) in list.iter().enumerate() {
2406 if pos != 0 {
2407 buf.write_all(b", ")?;
2408 }
2409 Self::selection_to_sql_with_placeholder_count(
2410 dialect,
2411 buf,
2412 selection,
2413 placeholder_count,
2414 )?;
2415 }
2416 buf.write_all(b")")?;
2417 }
2418 };
2419 Ok(())
2420 }
2421
2422 fn update_to_sql(
2423 dialect: &dyn ToQuery,
2424 buf: &mut dyn Write,
2425 table: &str,
2426 assignments: &[UpdateAssignment],
2427 selection: Option<&Selection>,
2428 ) -> Result<()> {
2429 buf.write_all(b"UPDATE ")?;
2430 Self::write_quoted(dialect, buf, table)?;
2431 buf.write_all(b" SET ")?;
2432 for (pos, assignment) in assignments.iter().enumerate() {
2433 if pos != 0 {
2434 buf.write_all(b", ")?;
2435 }
2436 Self::write_quoted(dialect, buf, assignment.target.as_bytes())?;
2437 buf.write_all(b"=")?;
2438 match &assignment.value {
2439 UpdateValue::Null => buf.write_all(b"NULL")?,
2440 UpdateValue::String(string) => Self::write_single_quoted(dialect, buf, string)?,
2441 UpdateValue::Number(number) => buf.write_all(number.as_bytes())?,
2442 UpdateValue::Placeholder => {
2443 buf.write_all(dialect.placeholder(pos + 1).as_bytes())?
2444 }
2445 }
2446 }
2447 if let Some(selection) = selection.as_ref() {
2448 buf.write_all(b" WHERE ")?;
2449 Self::selection_to_sql(dialect, buf, selection)?;
2450 };
2451 Ok(())
2452 }
2453
2454 fn delete_to_sql(
2455 dialect: &dyn ToQuery,
2456 buf: &mut dyn Write,
2457 from_clause: &FromClause,
2458 selection: Option<&Selection>,
2459 ) -> Result<()> {
2460 buf.write_all(b"DELETE FROM ")?;
2461 match from_clause {
2462 FromClause::Table(name) => Self::write_quoted(dialect, buf, name)?,
2463 FromClause::None => Err(Error::DeleteToSql {
2464 reason: "DELETE without FROM is not supported",
2465 })?,
2466 FromClause::TableWithJoin(_) => Err(Error::DeleteToSql {
2467 reason: "DELETE with joins is not supported",
2468 })?,
2469 }
2470 if let Some(selection) = selection.as_ref() {
2471 buf.write_all(b" WHERE ")?;
2472 Self::selection_to_sql(dialect, buf, selection)?;
2473 };
2474 Ok(())
2475 }
2476
2477 fn drop_table_to_sql(
2478 dialect: &dyn ToQuery,
2479 buf: &mut dyn Write,
2480 if_exists: bool,
2481 name: &str,
2482 ) -> Result<()> {
2483 buf.write_all(b"DROP TABLE ")?;
2484 if if_exists {
2485 buf.write_all(b"IF EXISTS ")?;
2486 }
2487 Self::write_quoted(dialect, buf, name);
2488 Ok(())
2489 }
2490
2491 fn drop_index_to_sql(
2492 dialect: &dyn ToQuery,
2493 buf: &mut dyn Write,
2494 if_exists: bool,
2495 name: &str,
2496 table: &str,
2497 ) -> Result<()> {
2498 buf.write_all(b"DROP INDEX ")?;
2499 if if_exists {
2500 buf.write_all(b"IF EXISTS ")?;
2501 }
2502 Self::write_quoted(dialect, buf, name);
2503 if dialect.drop_index_requires_table() {
2504 buf.write_all(b" ON ")?;
2505 Self::write_quoted(dialect, buf, table)?;
2506 }
2507 Ok(())
2508 }
2509
2510 fn write_quoted(
2511 dialect: &dyn ToQuery,
2512 buf: &mut dyn Write,
2513 input: impl AsRef<[u8]>,
2514 ) -> Result<()> {
2515 buf.write_all(dialect.quote())?;
2516 buf.write_all(input.as_ref())?;
2517 buf.write_all(dialect.quote())?;
2518 Ok(())
2519 }
2520
2521 fn write_single_quoted(
2522 dialect: &dyn ToQuery,
2523 buf: &mut dyn Write,
2524 input: impl AsRef<[u8]>,
2525 ) -> Result<()> {
2526 buf.write_all(b"'")?;
2527 buf.write_all(input.as_ref())?;
2528 buf.write_all(b"'")?;
2529 Ok(())
2530 }
2531
2532 fn alter_table_to_sql(
2533 dialect: &dyn ToQuery,
2534 buf: &mut dyn Write,
2535 table_name: &str,
2536 operation: &AlterTableOperation,
2537 ) -> Result<()> {
2538 buf.write_all(b"ALTER TABLE ")?;
2539 Self::write_quoted(dialect, buf, table_name)?;
2540 match operation {
2541 AlterTableOperation::AddColumn { column } => {
2542 buf.write_all(b" ADD COLUMN ")?;
2543 let columns: &[Column] = slice::from_ref(column);
2544 Self::table_columns_to_sql(dialect, buf, columns, "")?;
2545 }
2546 AlterTableOperation::RenameColumn { from, to } => {
2547 buf.write_all(b" RENAME COLUMN ")?;
2548 Self::write_quoted(dialect, buf, from)?;
2549 buf.write_all(b" TO ")?;
2550 Self::write_quoted(dialect, buf, to)?;
2551 }
2552 AlterTableOperation::DropColumn { name } => {
2553 buf.write_all(b" DROP COLUMN ")?;
2554 Self::write_quoted(dialect, buf, name)?;
2555 }
2556 AlterTableOperation::RenameTable { to } => {
2557 buf.write_all(b" RENAME TO ")?;
2558 Self::write_quoted(dialect, buf, to)?;
2559 }
2560 }
2561 Ok(())
2562 }
2563
2564 pub fn to_sql(&self, dialect: &dyn ToQuery) -> Result<String> {
2565 let buf = &mut Cursor::new(Vec::with_capacity(1));
2566 match self {
2567 Ast::CreateTable {
2568 if_not_exists,
2569 name,
2570 columns,
2571 constraints,
2572 } => {
2573 Self::create_table_to_sql(dialect, buf, *if_not_exists, name, columns, constraints)?
2574 }
2575 Ast::AlterTable { name, operation } => {
2576 Self::alter_table_to_sql(dialect, buf, name.as_str(), operation)?
2577 }
2578 Ast::CreateIndex {
2579 unique,
2580 name,
2581 table,
2582 columns,
2583 } => Self::create_index_to_sql(dialect, buf, *unique, name, table, columns)?,
2584 Ast::Select {
2585 distinct,
2586 projections,
2587 from_clause,
2588 selection,
2589 group_by,
2590 order_by,
2591 } => Self::select_to_sql(
2592 dialect,
2593 buf,
2594 *distinct,
2595 projections,
2596 from_clause,
2597 selection.as_ref(),
2598 group_by,
2599 order_by,
2600 )?,
2601 Ast::Insert {
2602 table,
2603 columns,
2604 source,
2605 } => Self::insert_to_sql(
2606 dialect,
2607 buf,
2608 table.as_str(),
2609 columns.as_slice(),
2610 source.as_slice(),
2611 )?,
2612 Ast::Update {
2613 table,
2614 assignments,
2615 selection,
2616 } => Self::update_to_sql(
2617 dialect,
2618 buf,
2619 table.as_str(),
2620 assignments.as_slice(),
2621 selection.as_ref(),
2622 )?,
2623 Ast::Delete {
2624 from_clause,
2625 selection,
2626 } => Self::delete_to_sql(dialect, buf, from_clause, selection.as_ref())?,
2627 Ast::DropTable { if_exists, name } => {
2628 Self::drop_table_to_sql(dialect, buf, *if_exists, name)?
2629 }
2630 Ast::DropIndex {
2631 if_exists,
2632 name,
2633 table,
2634 } => Self::drop_index_to_sql(dialect, buf, *if_exists, name, table)?,
2635 };
2636 let buf = std::mem::replace(buf, Cursor::new(Vec::new()));
2637 Ok(String::from_utf8(buf.into_inner())?)
2638 }
2639}
2640
2641pub trait ToQuery {
2642 fn quote(&self) -> &'static [u8];
2643
2644 fn placeholder(&self, pos: usize) -> Cow<'static, str>;
2645
2646 fn placeholder_supports_cast(&self) -> bool {
2647 false
2648 }
2649
2650 fn emit_column_spec(&self, column: &Column, buf: &mut dyn Write) -> Result<()>;
2651
2652 fn drop_index_requires_table(&self) -> bool {
2653 false
2654 }
2655}
2656
2657impl ToQuery for MySqlDialect {
2658 fn quote(&self) -> &'static [u8] {
2659 b"`"
2660 }
2661
2662 fn placeholder(&self, _: usize) -> Cow<'static, str> {
2663 Cow::Borrowed("?")
2664 }
2665
2666 fn emit_column_spec(
2667 &self,
2668 Column {
2669 name,
2670 data_type,
2671 options,
2672 }: &Column,
2673 buf: &mut dyn Write,
2674 ) -> Result<()> {
2675 let mut options = *options;
2676 let spec = match data_type {
2677 DataType::SmallSerial if options.is_primary_key() => {
2678 options = options.set_auto_increment();
2679 Cow::Borrowed("SMALLINT")
2680 }
2681 DataType::Serial if options.is_primary_key() => {
2682 options = options.set_auto_increment();
2683 Cow::Borrowed("INT")
2684 }
2685 DataType::BigSerial if options.is_primary_key() => {
2686 options = options.set_auto_increment();
2687 Cow::Borrowed("BIGINT")
2688 }
2689 DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2690 DataType::I16 => Cow::Borrowed("SMALLLINT"),
2691 DataType::I32 => Cow::Borrowed("INT"),
2692 DataType::I64 => Cow::Borrowed("BIGINT"),
2693 DataType::F32 => Cow::Borrowed("REAL"),
2694 DataType::F64 => Cow::Borrowed("DOUBLE"),
2695 DataType::Bool => Cow::Borrowed("BOOLEAN"),
2696 DataType::String => Cow::Borrowed("TEXT"),
2697 DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2698 DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2699 DataType::Bytes => Cow::Borrowed("BLOB"),
2700 DataType::Json => Cow::Borrowed("JSON"),
2701 DataType::Uuid => Cow::Borrowed("CHAR(36)"),
2702 DataType::Decimal { precision, scale } => {
2703 Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2704 }
2705 DataType::Date => Cow::Borrowed("DATE"),
2706 DataType::Time => Cow::Borrowed("TIME"),
2707 DataType::Timestamp => Cow::Borrowed("DATETIME"),
2708 };
2709
2710 buf.write_all(spec.as_bytes())?;
2711 let options = options
2712 .into_iter()
2713 .map(|option| match option {
2714 ColumnOption::PrimaryKey => "PRIMARY KEY",
2715 ColumnOption::AutoInrement => "AUTO_INCREMENT",
2716 ColumnOption::NotNull => "NOT NULL",
2717 ColumnOption::Nullable => "NULL",
2718 ColumnOption::Unique => "UNIQUE",
2719 })
2720 .collect::<Vec<_>>()
2721 .join(" ");
2722 if !options.is_empty() {
2723 buf.write_all(b" ")?;
2724 buf.write_all(options.as_bytes())?;
2725 }
2726 Ok(())
2727 }
2728
2729 fn drop_index_requires_table(&self) -> bool {
2730 true
2731 }
2732}
2733
2734impl ToQuery for PostgreSqlDialect {
2735 fn quote(&self) -> &'static [u8] {
2736 b"\""
2737 }
2738
2739 fn placeholder(&self, pos: usize) -> Cow<'static, str> {
2740 Cow::Owned(format!("${pos}"))
2741 }
2742
2743 fn placeholder_supports_cast(&self) -> bool {
2744 true
2745 }
2746
2747 fn emit_column_spec(
2748 &self,
2749 Column {
2750 name,
2751 data_type,
2752 options,
2753 }: &Column,
2754 buf: &mut dyn Write,
2755 ) -> Result<()> {
2756 let mut options = *options;
2757 let spec = match data_type {
2758 DataType::SmallSerial if options.is_primary_key() => Cow::Borrowed("SMALLSERIAL"),
2759 DataType::Serial if options.is_primary_key() => Cow::Borrowed("SERIAL"),
2760 DataType::BigSerial if options.is_primary_key() => Cow::Borrowed("BIGSERIAL"),
2761 DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2762 DataType::I16 if options.is_primary_key() && options.is_auto_increment() => {
2763 Cow::Borrowed("SMALLSERIAL")
2764 }
2765 DataType::I32 if options.is_primary_key() && options.is_auto_increment() => {
2766 Cow::Borrowed("SERIAL")
2767 }
2768 DataType::I64 if options.is_primary_key() && options.is_auto_increment() => {
2769 Cow::Borrowed("BIGSERIAL")
2770 }
2771 DataType::I16 => Cow::Borrowed("SMALLLINT"),
2772 DataType::I32 => Cow::Borrowed("INT"),
2773 DataType::I64 => Cow::Borrowed("BIGINT"),
2774 DataType::F32 => Cow::Borrowed("REAL"),
2775 DataType::F64 => Cow::Borrowed("DOUBLE"),
2776 DataType::Bool => Cow::Borrowed("BOOLEAN"),
2777 DataType::String => Cow::Borrowed("TEXT"),
2778 DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2779 DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2780 DataType::Bytes => Cow::Borrowed("BYTEA"),
2781 DataType::Json => Cow::Borrowed("JSON"),
2782 DataType::Uuid => Cow::Borrowed("UUID"),
2783 DataType::Decimal { precision, scale } => {
2784 Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2785 }
2786 DataType::Date => Cow::Borrowed("DATE"),
2787 DataType::Time => Cow::Borrowed("TIME"),
2788 DataType::Timestamp => Cow::Borrowed("TIMESTAMP"),
2789 };
2790 buf.write_all(spec.as_bytes())?;
2791 let options = options
2792 .into_iter()
2793 .filter_map(|option| match option {
2794 ColumnOption::PrimaryKey => Some("PRIMARY KEY"),
2795 ColumnOption::AutoInrement => None,
2796 ColumnOption::NotNull => Some("NOT NULL"),
2797 ColumnOption::Nullable => Some("NULL"),
2798 ColumnOption::Unique => Some("UNIQUE"),
2799 })
2800 .collect::<Vec<_>>()
2801 .join(" ");
2802 if !options.is_empty() {
2803 buf.write_all(b" ")?;
2804 buf.write_all(options.as_bytes())?;
2805 }
2806 Ok(())
2807 }
2808}
2809
2810impl ToQuery for SQLiteDialect {
2811 fn quote(&self) -> &'static [u8] {
2812 b"`"
2813 }
2814
2815 fn placeholder(&self, _: usize) -> Cow<'static, str> {
2816 Cow::Borrowed("?")
2817 }
2818
2819 fn emit_column_spec(
2820 &self,
2821 Column {
2822 name,
2823 data_type,
2824 options,
2825 }: &Column,
2826 buf: &mut dyn Write,
2827 ) -> Result<()> {
2828 let mut options = *options;
2829 let spec = match data_type {
2830 DataType::SmallSerial | DataType::Serial | DataType::BigSerial
2831 if options.is_primary_key() =>
2832 {
2833 Cow::Borrowed("INTEGER")
2834 }
2835 DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2836 DataType::I16 | DataType::I32 | DataType::I64 if options.is_primary_key() => {
2837 options = options.unset_auto_increment();
2840 Cow::Borrowed("INTEGER")
2841 }
2842 DataType::I32 => Cow::Borrowed("INTEGER"),
2843 DataType::I64 => Cow::Borrowed("INTEGER"),
2844 DataType::I16 => Cow::Borrowed("INTEGER"),
2845 DataType::I32 => Cow::Borrowed("INTEGER"),
2846 DataType::I64 => Cow::Borrowed("INTEGER"),
2847 DataType::F32 => Cow::Borrowed("FLOAT"),
2848 DataType::F64 => Cow::Borrowed("DOUBLE"),
2849 DataType::Bool => Cow::Borrowed("BOOLEAN"),
2850 DataType::String => Cow::Borrowed("TEXT"),
2851 DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2852 DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2853 DataType::Bytes => Cow::Borrowed("BLOB"),
2854 DataType::Json => Cow::Borrowed("JSON"),
2855 DataType::Uuid => Cow::Borrowed("UUID"),
2856 DataType::Decimal { precision, scale } => {
2857 Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2858 }
2859 DataType::Date => Cow::Borrowed("TEXT"),
2860 DataType::Time => Cow::Borrowed("TEXT"),
2861 DataType::Timestamp => Cow::Borrowed("TEXT"),
2862 };
2863 buf.write_all(spec.as_bytes())?;
2864 let options = options
2865 .into_iter()
2866 .map(|option| match option {
2867 ColumnOption::PrimaryKey => "PRIMARY KEY",
2868 ColumnOption::AutoInrement => "AUTOINCREMENT",
2869 ColumnOption::NotNull => "NOT NULL",
2870 ColumnOption::Nullable => "NULL",
2871 ColumnOption::Unique => "UNIQUE",
2872 })
2873 .collect::<Vec<_>>()
2874 .join(" ");
2875 if !options.is_empty() {
2876 buf.write_all(b" ")?;
2877 buf.write_all(options.as_bytes())?;
2878 }
2879 Ok(())
2880 }
2881}