Skip to content

Commit

Permalink
Parse INSERT with subquery when lacking column names
Browse files Browse the repository at this point in the history
Adds support to parse the example scenario:
```sql
INSERT INTO t1 (SELECT 1)
```

The parser previously looked to parse the subquery
as a parenthesized list of column names which was
incorrect in this case.
  • Loading branch information
iffyio committed Dec 11, 2024
1 parent 00abaf2 commit fe84a75
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
25 changes: 19 additions & 6 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11329,14 +11329,19 @@ impl<'a> Parser<'a> {
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, partitioned, after_columns) = if !self.peek_subquery_start() {
let columns = self.parse_parenthesized_column_list(Optional, is_mysql)?;

let partitioned = self.parse_insert_partition()?;
// 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)?
let partitioned = self.parse_insert_partition()?;
// 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)?
} else {
vec![]
};
(columns, partitioned, after_columns)
} else {
vec![]
Default::default()
};

let source = Some(self.parse_query()?);
Expand Down Expand Up @@ -11431,6 +11436,14 @@ impl<'a> Parser<'a> {
}
}

/// Returns true if the immediate tokens look like the
/// beginning of a subquery. `(SELECT ...`
fn peek_subquery_start(&mut self) -> bool {
let [maybe_lparen, maybe_select] = self.peek_tokens();
Token::LParen == maybe_lparen
&& matches!(maybe_select, Token::Word(w) if w.keyword == Keyword::SELECT)
}

fn parse_conflict_clause(&mut self) -> Option<SqliteOnConflict> {
if self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]) {
Some(SqliteOnConflict::Replace)
Expand Down
2 changes: 2 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10964,6 +10964,8 @@ fn insert_into_with_parentheses() {
Box::new(GenericDialect {}),
]);
dialects.verified_stmt("INSERT INTO t1 (id, name) (SELECT t2.id, t2.name FROM t2)");
dialects.verified_stmt("INSERT INTO t1 (SELECT t2.id, t2.name FROM t2)");
dialects.verified_stmt(r#"INSERT INTO t1 ("select", name) (SELECT t2.name FROM t2)"#);
}

#[test]
Expand Down

0 comments on commit fe84a75

Please sign in to comment.