Support INSERT INTO ... DEFAULT VALUES ... (#1036)

This commit is contained in:
Drew Thomas 2023-11-22 07:21:26 +11:00 committed by GitHub
parent 5bdf2e6608
commit 3d2773a794
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 25 deletions

View file

@ -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}")?;

View file

@ -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)?;

View file

@ -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 {};

View file

@ -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!(

View file

@ -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");