Skip to content

Commit 810c70d

Browse files
Merge branch 'main' into raiserror-mssql
2 parents 8d140b0 + 36db176 commit 810c70d

28 files changed

+2204
-400
lines changed

src/ast/ddl.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@ pub enum AlterTableOperation {
115115
DropConstraint {
116116
if_exists: bool,
117117
name: Ident,
118-
cascade: bool,
118+
drop_behavior: Option<DropBehavior>,
119119
},
120120
/// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
121121
DropColumn {
122122
column_name: Ident,
123123
if_exists: bool,
124-
cascade: bool,
124+
drop_behavior: Option<DropBehavior>,
125125
},
126126
/// `ATTACH PART|PARTITION <partition_expr>`
127127
/// Note: this is a ClickHouse-specific operation, please refer to
@@ -451,27 +451,35 @@ impl fmt::Display for AlterTableOperation {
451451
AlterTableOperation::DropConstraint {
452452
if_exists,
453453
name,
454-
cascade,
454+
drop_behavior,
455455
} => {
456456
write!(
457457
f,
458458
"DROP CONSTRAINT {}{}{}",
459459
if *if_exists { "IF EXISTS " } else { "" },
460460
name,
461-
if *cascade { " CASCADE" } else { "" },
461+
match drop_behavior {
462+
None => "",
463+
Some(DropBehavior::Restrict) => " RESTRICT",
464+
Some(DropBehavior::Cascade) => " CASCADE",
465+
}
462466
)
463467
}
464468
AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"),
465469
AlterTableOperation::DropColumn {
466470
column_name,
467471
if_exists,
468-
cascade,
472+
drop_behavior,
469473
} => write!(
470474
f,
471475
"DROP COLUMN {}{}{}",
472476
if *if_exists { "IF EXISTS " } else { "" },
473477
column_name,
474-
if *cascade { " CASCADE" } else { "" }
478+
match drop_behavior {
479+
None => "",
480+
Some(DropBehavior::Restrict) => " RESTRICT",
481+
Some(DropBehavior::Cascade) => " CASCADE",
482+
}
475483
),
476484
AlterTableOperation::AttachPartition { partition } => {
477485
write!(f, "ATTACH {partition}")
@@ -1786,6 +1794,26 @@ impl fmt::Display for ReferentialAction {
17861794
}
17871795
}
17881796

1797+
/// `<drop behavior> ::= CASCADE | RESTRICT`.
1798+
///
1799+
/// Used in `DROP` statements.
1800+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1801+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1802+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1803+
pub enum DropBehavior {
1804+
Restrict,
1805+
Cascade,
1806+
}
1807+
1808+
impl fmt::Display for DropBehavior {
1809+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1810+
f.write_str(match self {
1811+
DropBehavior::Restrict => "RESTRICT",
1812+
DropBehavior::Cascade => "CASCADE",
1813+
})
1814+
}
1815+
}
1816+
17891817
/// SQL user defined type definition
17901818
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
17911819
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

src/ast/dml.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ use sqlparser_derive::{Visit, VisitMut};
3232
pub use super::ddl::{ColumnDef, TableConstraint};
3333

3434
use super::{
35-
display_comma_separated, display_separated, ClusteredBy, CommentDef, Expr, FileFormat,
36-
FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident,
37-
InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert, OneOrManyWithParens,
38-
OrderByExpr, Query, RowAccessPolicy, SelectItem, SqlOption, SqliteOnConflict, TableEngine,
39-
TableWithJoins, Tag, WrappedCollection,
35+
display_comma_separated, display_separated, query::InputFormatClause, Assignment, ClusteredBy,
36+
CommentDef, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat,
37+
HiveRowFormat, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert,
38+
OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem, Setting, SqlOption,
39+
SqliteOnConflict, TableEngine, TableObject, TableWithJoins, Tag, WrappedCollection,
4040
};
4141

4242
/// CREATE INDEX statement.
@@ -470,8 +470,7 @@ pub struct Insert {
470470
/// INTO - optional keyword
471471
pub into: bool,
472472
/// TABLE
473-
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
474-
pub table_name: ObjectName,
473+
pub table: TableObject,
475474
/// table_name as foo (for PostgreSQL)
476475
pub table_alias: Option<Ident>,
477476
/// COLUMNS
@@ -480,12 +479,15 @@ pub struct Insert {
480479
pub overwrite: bool,
481480
/// A SQL query that specifies what to insert
482481
pub source: Option<Box<Query>>,
482+
/// MySQL `INSERT INTO ... SET`
483+
/// See: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
484+
pub assignments: Vec<Assignment>,
483485
/// partitioned insert (Hive)
484486
pub partitioned: Option<Vec<Expr>>,
485487
/// Columns defined after PARTITION
486488
pub after_columns: Vec<Ident>,
487489
/// whether the insert has the table keyword (Hive)
488-
pub table: bool,
490+
pub has_table_keyword: bool,
489491
pub on: Option<OnInsert>,
490492
/// RETURNING
491493
pub returning: Option<Vec<SelectItem>>,
@@ -495,14 +497,27 @@ pub struct Insert {
495497
pub priority: Option<MysqlInsertPriority>,
496498
/// Only for mysql
497499
pub insert_alias: Option<InsertAliases>,
500+
/// Settings used for ClickHouse.
501+
///
502+
/// ClickHouse syntax: `INSERT INTO tbl SETTINGS format_template_resultset = '/some/path/resultset.format'`
503+
///
504+
/// [ClickHouse `INSERT INTO`](https://clickhouse.com/docs/en/sql-reference/statements/insert-into)
505+
pub settings: Option<Vec<Setting>>,
506+
/// Format for `INSERT` statement when not using standard SQL format. Can be e.g. `CSV`,
507+
/// `JSON`, `JSONAsString`, `LineAsString` and more.
508+
///
509+
/// ClickHouse syntax: `INSERT INTO tbl FORMAT JSONEachRow {"foo": 1, "bar": 2}, {"foo": 3}`
510+
///
511+
/// [ClickHouse formats JSON insert](https://clickhouse.com/docs/en/interfaces/formats#json-inserting-data)
512+
pub format_clause: Option<InputFormatClause>,
498513
}
499514

500515
impl Display for Insert {
501516
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502517
let table_name = if let Some(alias) = &self.table_alias {
503-
format!("{0} AS {alias}", self.table_name)
518+
format!("{0} AS {alias}", self.table)
504519
} else {
505-
self.table_name.to_string()
520+
self.table.to_string()
506521
};
507522

508523
if let Some(on_conflict) = self.or {
@@ -528,7 +543,7 @@ impl Display for Insert {
528543
ignore = if self.ignore { " IGNORE" } else { "" },
529544
over = if self.overwrite { " OVERWRITE" } else { "" },
530545
int = if self.into { " INTO" } else { "" },
531-
tbl = if self.table { " TABLE" } else { "" },
546+
tbl = if self.has_table_keyword { " TABLE" } else { "" },
532547
)?;
533548
}
534549
if !self.columns.is_empty() {
@@ -543,11 +558,18 @@ impl Display for Insert {
543558
write!(f, "({}) ", display_comma_separated(&self.after_columns))?;
544559
}
545560

546-
if let Some(source) = &self.source {
547-
write!(f, "{source}")?;
561+
if let Some(settings) = &self.settings {
562+
write!(f, "SETTINGS {} ", display_comma_separated(settings))?;
548563
}
549564

550-
if self.source.is_none() && self.columns.is_empty() {
565+
if let Some(source) = &self.source {
566+
write!(f, "{source}")?;
567+
} else if !self.assignments.is_empty() {
568+
write!(f, "SET ")?;
569+
write!(f, "{}", display_comma_separated(&self.assignments))?;
570+
} else if let Some(format_clause) = &self.format_clause {
571+
write!(f, "{format_clause}")?;
572+
} else if self.columns.is_empty() {
551573
write!(f, "DEFAULT VALUES")?;
552574
}
553575

src/ast/helpers/stmt_create_table.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,11 @@ mod tests {
548548

549549
#[test]
550550
pub fn test_from_invalid_statement() {
551-
let stmt = Statement::Commit { chain: false };
551+
let stmt = Statement::Commit {
552+
chain: false,
553+
end: false,
554+
modifier: None,
555+
};
552556

553557
assert_eq!(
554558
CreateTableBuilder::try_from(stmt).unwrap_err(),

src/ast/helpers/stmt_data_loading.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use core::fmt::Formatter;
2929
#[cfg(feature = "serde")]
3030
use serde::{Deserialize, Serialize};
3131

32-
use crate::ast::Ident;
32+
use crate::ast::{Ident, ObjectName};
3333
#[cfg(feature = "visitor")]
3434
use sqlparser_derive::{Visit, VisitMut};
3535

@@ -156,3 +156,22 @@ impl fmt::Display for StageLoadSelectItem {
156156
Ok(())
157157
}
158158
}
159+
160+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
161+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
162+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
163+
pub struct FileStagingCommand {
164+
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
165+
pub stage: ObjectName,
166+
pub pattern: Option<String>,
167+
}
168+
169+
impl fmt::Display for FileStagingCommand {
170+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171+
write!(f, "{}", self.stage)?;
172+
if let Some(pattern) = self.pattern.as_ref() {
173+
write!(f, " PATTERN='{pattern}'")?;
174+
}
175+
Ok(())
176+
}
177+
}

0 commit comments

Comments
 (0)