Skip to content

Commit bc25af8

Browse files
committed
Support PostgreSQL INSERT INTO ... DEFAULT VALUES ...
1 parent 4cdaa40 commit bc25af8

File tree

5 files changed

+55
-14
lines changed

5 files changed

+55
-14
lines changed

src/ast/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,7 +1385,7 @@ pub enum Statement {
13851385
/// Overwrite (Hive)
13861386
overwrite: bool,
13871387
/// A SQL query that specifies what to insert
1388-
source: Box<Query>,
1388+
source: Option<Box<Query>>,
13891389
/// partitioned insert (Hive)
13901390
partitioned: Option<Vec<Expr>>,
13911391
/// Columns defined after PARTITION
@@ -2241,7 +2241,14 @@ impl fmt::Display for Statement {
22412241
if !after_columns.is_empty() {
22422242
write!(f, "({}) ", display_comma_separated(after_columns))?;
22432243
}
2244-
write!(f, "{source}")?;
2244+
2245+
if let Some(source) = source {
2246+
write!(f, "{source}")?;
2247+
}
2248+
2249+
if source.is_none() && columns.is_empty() {
2250+
write!(f, "DEFAULT VALUES")?;
2251+
}
22452252

22462253
if let Some(on) = on {
22472254
write!(f, "{on}")?;

src/parser/mod.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7090,7 +7090,16 @@ impl<'a> Parser<'a> {
70907090
let table = self.parse_keyword(Keyword::TABLE);
70917091
let table_name = self.parse_object_name()?;
70927092
let is_mysql = dialect_of!(self is MySqlDialect);
7093-
let columns = self.parse_parenthesized_column_list(Optional, is_mysql)?;
7093+
let is_postgresql = dialect_of!(self is PostgreSqlDialect);
7094+
7095+
let is_postgresql_default_values =
7096+
is_postgresql && self.parse_keywords(&[Keyword::DEFAULT, Keyword::VALUES]);
7097+
7098+
let columns: Vec<Ident> = if !is_postgresql_default_values {
7099+
self.parse_parenthesized_column_list(Optional, is_mysql)?
7100+
} else {
7101+
vec![]
7102+
};
70947103

70957104
let partitioned = if self.parse_keyword(Keyword::PARTITION) {
70967105
self.expect_token(&Token::LParen)?;
@@ -7104,7 +7113,12 @@ impl<'a> Parser<'a> {
71047113
// Hive allows you to specify columns after partitions as well if you want.
71057114
let after_columns = self.parse_parenthesized_column_list(Optional, false)?;
71067115

7107-
let source = Box::new(self.parse_query()?);
7116+
let source = if !is_postgresql_default_values {
7117+
Some(Box::new(self.parse_query()?))
7118+
} else {
7119+
None
7120+
};
7121+
71087122
let on = if self.parse_keyword(Keyword::ON) {
71097123
if self.parse_keyword(Keyword::CONFLICT) {
71107124
let conflict_target =

tests/sqlparser_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn parse_insert_values() {
9393
for (index, column) in columns.iter().enumerate() {
9494
assert_eq!(column, &Ident::new(expected_columns[index].clone()));
9595
}
96-
match &*source.body {
96+
match &*source.as_ref().unwrap().body {
9797
SetExpr::Values(Values { rows, .. }) => {
9898
assert_eq!(rows.as_slice(), expected_rows)
9999
}

tests/sqlparser_mysql.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ fn parse_simple_insert() {
937937
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
938938
assert!(on.is_none());
939939
assert_eq!(
940-
Box::new(Query {
940+
Some(Box::new(Query {
941941
with: None,
942942
body: Box::new(SetExpr::Values(Values {
943943
explicit_row: false,
@@ -964,7 +964,7 @@ fn parse_simple_insert() {
964964
offset: None,
965965
fetch: None,
966966
locks: vec![],
967-
}),
967+
})),
968968
source
969969
);
970970
}
@@ -990,7 +990,7 @@ fn parse_ignore_insert() {
990990
assert!(on.is_none());
991991
assert!(ignore);
992992
assert_eq!(
993-
Box::new(Query {
993+
Some(Box::new(Query {
994994
with: None,
995995
body: Box::new(SetExpr::Values(Values {
996996
explicit_row: false,
@@ -1005,7 +1005,7 @@ fn parse_ignore_insert() {
10051005
offset: None,
10061006
fetch: None,
10071007
locks: vec![]
1008-
}),
1008+
})),
10091009
source
10101010
);
10111011
}
@@ -1029,7 +1029,7 @@ fn parse_empty_row_insert() {
10291029
assert!(columns.is_empty());
10301030
assert!(on.is_none());
10311031
assert_eq!(
1032-
Box::new(Query {
1032+
Some(Box::new(Query {
10331033
with: None,
10341034
body: Box::new(SetExpr::Values(Values {
10351035
explicit_row: false,
@@ -1041,7 +1041,7 @@ fn parse_empty_row_insert() {
10411041
offset: None,
10421042
fetch: None,
10431043
locks: vec![],
1044-
}),
1044+
})),
10451045
source
10461046
);
10471047
}
@@ -1077,7 +1077,7 @@ fn parse_insert_with_on_duplicate_update() {
10771077
columns
10781078
);
10791079
assert_eq!(
1080-
Box::new(Query {
1080+
Some(Box::new(Query {
10811081
with: None,
10821082
body: Box::new(SetExpr::Values(Values {
10831083
explicit_row: false,
@@ -1100,7 +1100,7 @@ fn parse_insert_with_on_duplicate_update() {
11001100
offset: None,
11011101
fetch: None,
11021102
locks: vec![],
1103-
}),
1103+
})),
11041104
source
11051105
);
11061106
assert_eq!(

tests/sqlparser_postgres.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ fn parse_prepare() {
13831383
Expr::Identifier("a2".into()),
13841384
Expr::Identifier("a3".into()),
13851385
]];
1386-
match &*source.body {
1386+
match &*source.as_ref().unwrap().body {
13871387
SetExpr::Values(Values { rows, .. }) => {
13881388
assert_eq!(rows.as_slice(), &expected_values)
13891389
}
@@ -3502,3 +3502,23 @@ fn parse_join_constraint_unnest_alias() {
35023502
}]
35033503
);
35043504
}
3505+
3506+
// TODO: more tests with `ON CONFLICT`, `RETURNING`, ... any others?
3507+
#[test]
3508+
fn parse_insert_default_values() {
3509+
let stmt = pg().verified_stmt("INSERT INTO users DEFAULT VALUES");
3510+
3511+
match stmt {
3512+
Statement::Insert {
3513+
columns,
3514+
source,
3515+
table_name,
3516+
..
3517+
} => {
3518+
assert_eq!(columns, vec![]);
3519+
assert_eq!(source, None);
3520+
assert_eq!(table_name, ObjectName(vec!["users".into()]));
3521+
}
3522+
_ => unreachable!(),
3523+
}
3524+
}

0 commit comments

Comments
 (0)