Skip to content

Commit 174bda1

Browse files
committed
[MySQL, Oracle] Parse optimizer hints for MERGEs
1 parent 34c06e8 commit 174bda1

4 files changed

Lines changed: 26 additions & 6 deletions

File tree

src/ast/dml.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ impl Display for Update {
348348
pub struct Merge {
349349
/// The `MERGE` token that starts the statement.
350350
pub merge_token: AttachedToken,
351+
/// A query optimizer hint
352+
///
353+
/// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
354+
pub optimizer_hint: Option<OptimizerHint>,
351355
/// optional INTO keyword
352356
pub into: bool,
353357
/// Specifies the table to merge
@@ -364,13 +368,16 @@ pub struct Merge {
364368

365369
impl Display for Merge {
366370
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367-
write!(
368-
f,
369-
"MERGE{int} {table} USING {source} ",
370-
int = if self.into { " INTO" } else { "" },
371+
f.write_str("MERGE")?;
372+
if let Some(hint) = self.optimizer_hint.as_ref() {
373+
write!(f, " {hint}")?;
374+
}
375+
if self.into {
376+
write!(f, " INTO")?;
377+
}
378+
write!(f, " {table} USING {source} ",
371379
table = self.table,
372-
source = self.source,
373-
)?;
380+
source = self.source)?;
374381
write!(f, "ON {on} ", on = self.on)?;
375382
write!(f, "{}", display_separated(&self.clauses, " "))?;
376383
if let Some(ref output) = self.output {

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2819,6 +2819,7 @@ WHERE id = 1
28192819
// ~ individual tokens within the statement
28202820
let Statement::Merge(Merge {
28212821
merge_token,
2822+
optimizer_hint: _,
28222823
into: _,
28232824
table: _,
28242825
source: _,

src/parser/merge.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ impl Parser<'_> {
4141

4242
/// Parse a `MERGE` statement
4343
pub fn parse_merge(&mut self, merge_token: TokenWithSpan) -> Result<Statement, ParserError> {
44+
let optimizer_hint = self.parse_optional_optimizer_hint()?;
45+
4446
let into = self.parse_keyword(Keyword::INTO);
4547

4648
let table = self.parse_table_factor()?;
@@ -57,6 +59,7 @@ impl Parser<'_> {
5759

5860
Ok(Statement::Merge(Merge {
5961
merge_token: merge_token.into(),
62+
optimizer_hint,
6063
into,
6164
table,
6265
source,

tests/sqlparser_oracle.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,4 +380,13 @@ fn test_optimizer_hints() {
380380
// ~ deletes
381381
oracle_dialect.verified_stmt(
382382
"DELETE --+ ENABLE_PARALLEL_DML\n FROM table_name");
383+
384+
// ~ merges
385+
oracle_dialect.verified_stmt(
386+
"MERGE /*+ CLUSTERING */ INTO people_target pt \
387+
USING people_source ps \
388+
ON (pt.person_id = ps.person_id) \
389+
WHEN NOT MATCHED THEN INSERT \
390+
(pt.person_id, pt.first_name, pt.last_name, pt.title) \
391+
VALUES (ps.person_id, ps.first_name, ps.last_name, ps.title)");
383392
}

0 commit comments

Comments
 (0)