mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-04 13:10:31 +00:00
Support INSERT INTO ... DEFAULT VALUES ...
(#1036)
This commit is contained in:
parent
5bdf2e6608
commit
3d2773a794
5 changed files with 150 additions and 25 deletions
|
@ -1418,7 +1418,7 @@ pub enum Statement {
|
||||||
/// Overwrite (Hive)
|
/// Overwrite (Hive)
|
||||||
overwrite: bool,
|
overwrite: bool,
|
||||||
/// A SQL query that specifies what to insert
|
/// A SQL query that specifies what to insert
|
||||||
source: Box<Query>,
|
source: Option<Box<Query>>,
|
||||||
/// partitioned insert (Hive)
|
/// partitioned insert (Hive)
|
||||||
partitioned: Option<Vec<Expr>>,
|
partitioned: Option<Vec<Expr>>,
|
||||||
/// Columns defined after PARTITION
|
/// Columns defined after PARTITION
|
||||||
|
@ -2283,7 +2283,14 @@ impl fmt::Display for Statement {
|
||||||
if !after_columns.is_empty() {
|
if !after_columns.is_empty() {
|
||||||
write!(f, "({}) ", display_comma_separated(after_columns))?;
|
write!(f, "({}) ", display_comma_separated(after_columns))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(source) = source {
|
||||||
write!(f, "{source}")?;
|
write!(f, "{source}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if source.is_none() && columns.is_empty() {
|
||||||
|
write!(f, "DEFAULT VALUES")?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(on) = on {
|
if let Some(on) = on {
|
||||||
write!(f, "{on}")?;
|
write!(f, "{on}")?;
|
||||||
|
|
|
@ -7277,21 +7277,23 @@ impl<'a> Parser<'a> {
|
||||||
let table = self.parse_keyword(Keyword::TABLE);
|
let table = self.parse_keyword(Keyword::TABLE);
|
||||||
let table_name = self.parse_object_name()?;
|
let table_name = self.parse_object_name()?;
|
||||||
let is_mysql = dialect_of!(self is MySqlDialect);
|
let is_mysql = dialect_of!(self is MySqlDialect);
|
||||||
|
|
||||||
|
let (columns, partitioned, after_columns, source) =
|
||||||
|
if self.parse_keywords(&[Keyword::DEFAULT, Keyword::VALUES]) {
|
||||||
|
(vec![], None, vec![], None)
|
||||||
|
} else {
|
||||||
let columns = self.parse_parenthesized_column_list(Optional, is_mysql)?;
|
let columns = self.parse_parenthesized_column_list(Optional, is_mysql)?;
|
||||||
|
|
||||||
let partitioned = if self.parse_keyword(Keyword::PARTITION) {
|
let partitioned = self.parse_insert_partition()?;
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let r = Some(self.parse_comma_separated(Parser::parse_expr)?);
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
r
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hive allows you to specify columns after partitions as well if you want.
|
// Hive allows you to specify columns after partitions as well if you want.
|
||||||
let after_columns = self.parse_parenthesized_column_list(Optional, false)?;
|
let after_columns = self.parse_parenthesized_column_list(Optional, false)?;
|
||||||
|
|
||||||
let source = Box::new(self.parse_query()?);
|
let source = Some(Box::new(self.parse_query()?));
|
||||||
|
|
||||||
|
(columns, partitioned, after_columns, source)
|
||||||
|
};
|
||||||
|
|
||||||
let on = if self.parse_keyword(Keyword::ON) {
|
let on = if self.parse_keyword(Keyword::ON) {
|
||||||
if self.parse_keyword(Keyword::CONFLICT) {
|
if self.parse_keyword(Keyword::CONFLICT) {
|
||||||
let conflict_target =
|
let conflict_target =
|
||||||
|
@ -7362,6 +7364,17 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_insert_partition(&mut self) -> Result<Option<Vec<Expr>>, ParserError> {
|
||||||
|
if self.parse_keyword(Keyword::PARTITION) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let partition_cols = Some(self.parse_comma_separated(Parser::parse_expr)?);
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
Ok(partition_cols)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
|
||||||
let table = self.parse_table_and_joins()?;
|
let table = self.parse_table_and_joins()?;
|
||||||
self.expect_keyword(Keyword::SET)?;
|
self.expect_keyword(Keyword::SET)?;
|
||||||
|
|
|
@ -85,7 +85,7 @@ fn parse_insert_values() {
|
||||||
Statement::Insert {
|
Statement::Insert {
|
||||||
table_name,
|
table_name,
|
||||||
columns,
|
columns,
|
||||||
source,
|
source: Some(source),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(table_name.to_string(), expected_table_name);
|
assert_eq!(table_name.to_string(), expected_table_name);
|
||||||
|
@ -93,7 +93,7 @@ fn parse_insert_values() {
|
||||||
for (index, column) in columns.iter().enumerate() {
|
for (index, column) in columns.iter().enumerate() {
|
||||||
assert_eq!(column, &Ident::new(expected_columns[index].clone()));
|
assert_eq!(column, &Ident::new(expected_columns[index].clone()));
|
||||||
}
|
}
|
||||||
match &*source.body {
|
match *source.body {
|
||||||
SetExpr::Values(Values { rows, .. }) => {
|
SetExpr::Values(Values { rows, .. }) => {
|
||||||
assert_eq!(rows.as_slice(), expected_rows)
|
assert_eq!(rows.as_slice(), expected_rows)
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,111 @@ fn parse_insert_values() {
|
||||||
verified_stmt("INSERT INTO customer WITH foo AS (SELECT 1) SELECT * FROM foo UNION VALUES (1)");
|
verified_stmt("INSERT INTO customer WITH foo AS (SELECT 1) SELECT * FROM foo UNION VALUES (1)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_insert_default_values() {
|
||||||
|
let insert_with_default_values = verified_stmt("INSERT INTO test_table DEFAULT VALUES");
|
||||||
|
|
||||||
|
match insert_with_default_values {
|
||||||
|
Statement::Insert {
|
||||||
|
after_columns,
|
||||||
|
columns,
|
||||||
|
on,
|
||||||
|
partitioned,
|
||||||
|
returning,
|
||||||
|
source,
|
||||||
|
table_name,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
assert_eq!(columns, vec![]);
|
||||||
|
assert_eq!(after_columns, vec![]);
|
||||||
|
assert_eq!(on, None);
|
||||||
|
assert_eq!(partitioned, None);
|
||||||
|
assert_eq!(returning, None);
|
||||||
|
assert_eq!(source, None);
|
||||||
|
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let insert_with_default_values_and_returning =
|
||||||
|
verified_stmt("INSERT INTO test_table DEFAULT VALUES RETURNING test_column");
|
||||||
|
|
||||||
|
match insert_with_default_values_and_returning {
|
||||||
|
Statement::Insert {
|
||||||
|
after_columns,
|
||||||
|
columns,
|
||||||
|
on,
|
||||||
|
partitioned,
|
||||||
|
returning,
|
||||||
|
source,
|
||||||
|
table_name,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
assert_eq!(after_columns, vec![]);
|
||||||
|
assert_eq!(columns, vec![]);
|
||||||
|
assert_eq!(on, None);
|
||||||
|
assert_eq!(partitioned, None);
|
||||||
|
assert!(returning.is_some());
|
||||||
|
assert_eq!(source, None);
|
||||||
|
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let insert_with_default_values_and_on_conflict =
|
||||||
|
verified_stmt("INSERT INTO test_table DEFAULT VALUES ON CONFLICT DO NOTHING");
|
||||||
|
|
||||||
|
match insert_with_default_values_and_on_conflict {
|
||||||
|
Statement::Insert {
|
||||||
|
after_columns,
|
||||||
|
columns,
|
||||||
|
on,
|
||||||
|
partitioned,
|
||||||
|
returning,
|
||||||
|
source,
|
||||||
|
table_name,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
assert_eq!(after_columns, vec![]);
|
||||||
|
assert_eq!(columns, vec![]);
|
||||||
|
assert!(on.is_some());
|
||||||
|
assert_eq!(partitioned, None);
|
||||||
|
assert_eq!(returning, None);
|
||||||
|
assert_eq!(source, None);
|
||||||
|
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let insert_with_columns_and_default_values = "INSERT INTO test_table (test_col) DEFAULT VALUES";
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError(
|
||||||
|
"Expected SELECT, VALUES, or a subquery in the query body, found: DEFAULT".to_string()
|
||||||
|
),
|
||||||
|
parse_sql_statements(insert_with_columns_and_default_values).unwrap_err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let insert_with_default_values_and_hive_after_columns =
|
||||||
|
"INSERT INTO test_table DEFAULT VALUES (some_column)";
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected end of statement, found: (".to_string()),
|
||||||
|
parse_sql_statements(insert_with_default_values_and_hive_after_columns).unwrap_err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let insert_with_default_values_and_hive_partition =
|
||||||
|
"INSERT INTO test_table DEFAULT VALUES PARTITION (some_column)";
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected end of statement, found: PARTITION".to_string()),
|
||||||
|
parse_sql_statements(insert_with_default_values_and_hive_partition).unwrap_err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let insert_with_default_values_and_values_list = "INSERT INTO test_table DEFAULT VALUES (1)";
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected end of statement, found: (".to_string()),
|
||||||
|
parse_sql_statements(insert_with_default_values_and_values_list).unwrap_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_insert_sqlite() {
|
fn parse_insert_sqlite() {
|
||||||
let dialect = SQLiteDialect {};
|
let dialect = SQLiteDialect {};
|
||||||
|
|
|
@ -941,7 +941,7 @@ fn parse_simple_insert() {
|
||||||
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
|
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
|
||||||
assert!(on.is_none());
|
assert!(on.is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Box::new(Query {
|
Some(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
body: Box::new(SetExpr::Values(Values {
|
body: Box::new(SetExpr::Values(Values {
|
||||||
explicit_row: false,
|
explicit_row: false,
|
||||||
|
@ -969,7 +969,7 @@ fn parse_simple_insert() {
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
for_clause: None,
|
for_clause: None,
|
||||||
}),
|
})),
|
||||||
source
|
source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -995,7 +995,7 @@ fn parse_ignore_insert() {
|
||||||
assert!(on.is_none());
|
assert!(on.is_none());
|
||||||
assert!(ignore);
|
assert!(ignore);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Box::new(Query {
|
Some(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
body: Box::new(SetExpr::Values(Values {
|
body: Box::new(SetExpr::Values(Values {
|
||||||
explicit_row: false,
|
explicit_row: false,
|
||||||
|
@ -1011,7 +1011,7 @@ fn parse_ignore_insert() {
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
for_clause: None,
|
for_clause: None,
|
||||||
}),
|
})),
|
||||||
source
|
source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1035,7 +1035,7 @@ fn parse_empty_row_insert() {
|
||||||
assert!(columns.is_empty());
|
assert!(columns.is_empty());
|
||||||
assert!(on.is_none());
|
assert!(on.is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Box::new(Query {
|
Some(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
body: Box::new(SetExpr::Values(Values {
|
body: Box::new(SetExpr::Values(Values {
|
||||||
explicit_row: false,
|
explicit_row: false,
|
||||||
|
@ -1048,7 +1048,7 @@ fn parse_empty_row_insert() {
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
for_clause: None,
|
for_clause: None,
|
||||||
}),
|
})),
|
||||||
source
|
source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1084,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
columns
|
columns
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Box::new(Query {
|
Some(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
body: Box::new(SetExpr::Values(Values {
|
body: Box::new(SetExpr::Values(Values {
|
||||||
explicit_row: false,
|
explicit_row: false,
|
||||||
|
@ -1108,7 +1108,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
for_clause: None,
|
for_clause: None,
|
||||||
}),
|
})),
|
||||||
source
|
source
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1379,7 +1379,7 @@ fn parse_prepare() {
|
||||||
Statement::Insert {
|
Statement::Insert {
|
||||||
table_name,
|
table_name,
|
||||||
columns,
|
columns,
|
||||||
source,
|
source: Some(source),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(table_name.to_string(), "customers");
|
assert_eq!(table_name.to_string(), "customers");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue