Skip to content

Commit 45bb4de

Browse files
committed
[MySQL, Oracle] Parse optimizer hints for MERGEs
1 parent 491f70f commit 45bb4de

4 files changed

Lines changed: 25 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl Parser<'_> {
4343

4444
/// Parse a `MERGE` statement
4545
pub fn parse_merge(&mut self, merge_token: TokenWithSpan) -> Result<Merge, ParserError> {
46+
let optimizer_hint = self.parse_optional_optimizer_hint()?;
4647
let into = self.parse_keyword(Keyword::INTO);
4748

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

6061
Ok(Merge {
6162
merge_token: merge_token.into(),
63+
optimizer_hint,
6264
into,
6365
table,
6466
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)