Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/ast/dml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub struct Insert {
pub table_alias: Option<TableAliasWithoutColumns>,
/// COLUMNS
pub columns: Vec<ObjectName>,
/// BY NAME
pub by_name: bool,
/// Overwrite (Hive)
pub overwrite: bool,
/// A SQL query that specifies what to insert
Expand Down Expand Up @@ -201,6 +203,11 @@ impl Display for Insert {
}
}

if self.by_name {
write!(f, "BY NAME")?;
SpaceOrNewline.fmt(f)?;
}

if !self.after_columns.is_empty() {
write!(f, "({})", display_comma_separated(&self.after_columns))?;
SpaceOrNewline.fmt(f)?;
Expand Down
1 change: 1 addition & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ impl Spanned for Insert {
table,
table_alias,
columns,
by_name: _, // bool
overwrite: _, // bool
source,
partitioned,
Expand Down
1 change: 1 addition & 0 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,7 @@ fn parse_multi_table_insert(
table: TableObject::TableName(ObjectName(vec![])), // Not used for multi-table insert
table_alias: None,
columns: vec![],
by_name: false,
overwrite,
source: Some(source),
assignments: vec![],
Expand Down
5 changes: 5 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18404,7 +18404,9 @@ impl<'a> Parser<'a> {
let table = self.parse_keyword(Keyword::TABLE);
let table_object = self.parse_table_object()?;

// `BY NAME` is an INSERT clause, not a table alias.
let table_alias = if self.dialect.supports_insert_table_alias()
&& !self.peek_keywords(&[Keyword::BY, Keyword::NAME])
Comment on lines +18407 to +18409

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh this pattern looks a bit odd, would it make more sense to do the following?

let mut by_name = self.peek_keywords(&[BY, NAME]);
let table_alias = if ... // unchanged

// ...
let partitioned = self.parse_insert_partition()?;
by_name = by_name || self.parse_keywords(&[Keyword::BY, Keyword::NAME]);

&& !self.peek_sub_query()
&& self
.peek_one_of_keywords(&[Keyword::DEFAULT, Keyword::VALUES])
Expand All @@ -18428,6 +18430,7 @@ impl<'a> Parser<'a> {

let is_mysql = dialect_of!(self is MySqlDialect);

let mut by_name = false;
let (columns, partitioned, after_columns, output, source, assignments) = if self
.parse_keywords(&[Keyword::DEFAULT, Keyword::VALUES])
{
Expand All @@ -18438,6 +18441,7 @@ impl<'a> Parser<'a> {
self.parse_parenthesized_qualified_column_list(Optional, is_mysql)?;

let partitioned = self.parse_insert_partition()?;
by_name = self.parse_keywords(&[Keyword::BY, Keyword::NAME]);
// Hive allows you to specify columns after partitions as well if you want.
let after_columns = if dialect_of!(self is HiveDialect) {
self.parse_parenthesized_column_list(Optional, false)?
Expand Down Expand Up @@ -18562,6 +18566,7 @@ impl<'a> Parser<'a> {
ignore,
into,
overwrite,
by_name,
partitioned,
columns,
after_columns,
Expand Down
15 changes: 15 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19665,3 +19665,18 @@ fn parse_function_arg_call_chain_no_exponential_blowup() {
rx.recv_timeout(Duration::from_secs(5))
.expect("parser should reject this quickly, not loop exponentially");
}

#[test]
fn parse_insert_by_name() {
verified_stmt("INSERT INTO target BY NAME SELECT 1 AS a");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can also add some scenarios with table options that cover around the new option to ensure that parsing BY NAME isn't conflicting with other features that show up around it


match verified_stmt("INSERT INTO target (a) BY NAME SELECT 1 AS a") {
Statement::Insert(Insert {
by_name, columns, ..
}) => {
assert!(by_name);
assert_eq!(columns.len(), 1);
}
_ => unreachable!(),
}
}
31 changes: 31 additions & 0 deletions tests/sqlparser_databricks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,3 +737,34 @@ fn parse_cte_without_as() {
.parse_sql_statements("WITH cte (SELECT 1) SELECT * FROM cte")
.is_err());
}

#[test]
fn test_databricks_insert_by_name() {
match databricks_and_generic().verified_stmt("INSERT INTO target BY NAME SELECT 1 AS a") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove the AST assertion and rely on verified_stmt only for these, (AST is already covered in common)

Statement::Insert(Insert {
by_name,
columns,
has_table_keyword,
..
}) => {
assert!(by_name);
assert!(columns.is_empty());
assert!(!has_table_keyword);
}
_ => unreachable!(),
}

match databricks_and_generic().verified_stmt(
"INSERT INTO TABLE lakehouse.dwd.dwd_event_quality_sla_metric_di BY NAME WITH day AS (SELECT 1 AS event_data_id) SELECT event_data_id FROM day",
) {
Statement::Insert(Insert {
by_name,
has_table_keyword,
..
}) => {
assert!(by_name);
assert!(has_table_keyword);
}
_ => unreachable!(),
}
}
3 changes: 3 additions & 0 deletions tests/sqlparser_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6093,6 +6093,7 @@ fn test_simple_postgres_insert_with_alias() {
span: Span::empty(),
})
],
by_name: false,
overwrite: false,
source: Some(Box::new(Query {
with: None,
Expand Down Expand Up @@ -6173,6 +6174,7 @@ fn test_simple_postgres_insert_with_alias() {
span: Span::empty(),
})
],
by_name: false,
overwrite: false,
source: Some(Box::new(Query {
with: None,
Expand Down Expand Up @@ -6255,6 +6257,7 @@ fn test_simple_insert_with_quoted_alias() {
span: Span::empty(),
})
],
by_name: false,
overwrite: false,
source: Some(Box::new(Query {
with: None,
Expand Down
Loading