@@ -2549,20 +2549,23 @@ pub enum Statement {
25492549 /// RELEASE [ SAVEPOINT ] savepoint_name
25502550 /// ```
25512551 ReleaseSavepoint { name : Ident } ,
2552+ /// A `MERGE` statement.
2553+ ///
25522554 /// ```sql
2553- /// MERGE INTO <statement>
2555+ /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
25542556 /// ```
2555- /// Based on Snowflake. See <https://docs.snowflake.com/en/sql-reference/sql/merge.html>
2557+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
2558+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
25562559 Merge {
2557- // optional INTO keyword
2560+ /// optional INTO keyword
25582561 into : bool ,
2559- // Specifies the table to merge
2562+ /// Specifies the table to merge
25602563 table : TableFactor ,
2561- // Specifies the table or subquery to join with the target table
2564+ /// Specifies the table or subquery to join with the target table
25622565 source : TableFactor ,
2563- // Specifies the expression on which to join the target table and source
2566+ /// Specifies the expression on which to join the target table and source
25642567 on : Box < Expr > ,
2565- // Specifies the actions to perform when values match or do not match.
2568+ /// Specifies the actions to perform when values match or do not match.
25662569 clauses : Vec < MergeClause > ,
25672570 } ,
25682571 /// ```sql
@@ -5549,75 +5552,196 @@ impl fmt::Display for CopyLegacyCsvOption {
55495552 }
55505553}
55515554
5552- /// ` MERGE` Statement
5555+ /// Variant of `WHEN` clause used within a ` MERGE` Statement.
55535556///
5557+ /// Example:
55545558/// ```sql
5555- /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
5559+ /// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
55565560/// ```
5561+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
5562+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5563+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
5564+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
5565+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
5566+ pub enum MergeClauseKind {
5567+ /// `WHEN MATCHED`
5568+ Matched ,
5569+ /// `WHEN NOT MATCHED`
5570+ NotMatched ,
5571+ /// `WHEN MATCHED BY TARGET`
5572+ ///
5573+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5574+ NotMatchedByTarget ,
5575+ /// `WHEN MATCHED BY SOURCE`
5576+ ///
5577+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5578+ NotMatchedBySource ,
5579+ }
5580+
5581+ impl Display for MergeClauseKind {
5582+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
5583+ match self {
5584+ MergeClauseKind :: Matched => write ! ( f, "MATCHED" ) ,
5585+ MergeClauseKind :: NotMatched => write ! ( f, "NOT MATCHED" ) ,
5586+ MergeClauseKind :: NotMatchedByTarget => write ! ( f, "NOT MATCHED BY TARGET" ) ,
5587+ MergeClauseKind :: NotMatchedBySource => write ! ( f, "NOT MATCHED BY SOURCE" ) ,
5588+ }
5589+ }
5590+ }
5591+
5592+ /// The type of expression used to insert rows within a `MERGE` statement.
55575593///
5558- /// See [Snowflake documentation](https://docs.snowflake.com/en/sql-reference/sql/merge)
5594+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
5595+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
55595596#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
55605597#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
55615598#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
5562- pub enum MergeClause {
5563- MatchedUpdate {
5564- predicate : Option < Expr > ,
5565- assignments : Vec < Assignment > ,
5566- } ,
5567- MatchedDelete ( Option < Expr > ) ,
5568- NotMatched {
5569- predicate : Option < Expr > ,
5570- columns : Vec < Ident > ,
5571- values : Values ,
5572- } ,
5599+ pub enum MergeInsertKind {
5600+ /// The insert expression is defined from an explicit `VALUES` clause
5601+ ///
5602+ /// Example:
5603+ /// ```sql
5604+ /// INSERT VALUES(product, quantity)
5605+ /// ```
5606+ Values ( Values ) ,
5607+ /// The insert expression is defined using only the `ROW` keyword.
5608+ ///
5609+ /// Example:
5610+ /// ```sql
5611+ /// INSERT ROW
5612+ /// ```
5613+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5614+ Row ,
55735615}
55745616
5575- impl fmt :: Display for MergeClause {
5617+ impl Display for MergeInsertKind {
55765618 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
5577- use MergeClause :: * ;
5578- write ! ( f, "WHEN" ) ?;
55795619 match self {
5580- MatchedUpdate {
5581- predicate,
5582- assignments,
5583- } => {
5584- write ! ( f, " MATCHED" ) ?;
5585- if let Some ( pred) = predicate {
5586- write ! ( f, " AND {pred}" ) ?;
5587- }
5588- write ! (
5589- f,
5590- " THEN UPDATE SET {}" ,
5591- display_comma_separated( assignments)
5592- )
5620+ MergeInsertKind :: Values ( values) => {
5621+ write ! ( f, "{values}" )
55935622 }
5594- MatchedDelete ( predicate) => {
5595- write ! ( f, " MATCHED" ) ?;
5596- if let Some ( pred) = predicate {
5597- write ! ( f, " AND {pred}" ) ?;
5598- }
5599- write ! ( f, " THEN DELETE" )
5623+ MergeInsertKind :: Row => {
5624+ write ! ( f, "ROW" )
56005625 }
5601- NotMatched {
5602- predicate,
5603- columns,
5604- values,
5605- } => {
5606- write ! ( f, " NOT MATCHED" ) ?;
5607- if let Some ( pred) = predicate {
5608- write ! ( f, " AND {pred}" ) ?;
5609- }
5610- write ! (
5611- f,
5612- " THEN INSERT ({}) {}" ,
5613- display_comma_separated( columns) ,
5614- values
5615- )
5626+ }
5627+ }
5628+ }
5629+
5630+ /// The expression used to insert rows within a `MERGE` statement.
5631+ ///
5632+ /// Examples
5633+ /// ```sql
5634+ /// INSERT (product, quantity) VALUES(product, quantity)
5635+ /// INSERT ROW
5636+ /// ```
5637+ ///
5638+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
5639+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5640+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
5641+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
5642+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
5643+ pub struct MergeInsertExpr {
5644+ /// Columns (if any) specified by the insert.
5645+ ///
5646+ /// Example:
5647+ /// ```sql
5648+ /// INSERT (product, quantity) VALUES(product, quantity)
5649+ /// INSERT (product, quantity) ROW
5650+ /// ```
5651+ pub columns : Vec < Ident > ,
5652+ /// The insert type used by the statement.
5653+ pub kind : MergeInsertKind ,
5654+ }
5655+
5656+ impl Display for MergeInsertExpr {
5657+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
5658+ if !self . columns . is_empty ( ) {
5659+ write ! ( f, "({}) " , display_comma_separated( self . columns. as_slice( ) ) ) ?;
5660+ }
5661+ write ! ( f, "{}" , self . kind)
5662+ }
5663+ }
5664+
5665+ /// Underlying statement of a when clause within a `MERGE` Statement
5666+ ///
5667+ /// Example
5668+ /// ```sql
5669+ /// INSERT (product, quantity) VALUES(product, quantity)
5670+ /// ```
5671+ ///
5672+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
5673+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5674+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
5675+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
5676+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
5677+ pub enum MergeAction {
5678+ /// An `INSERT` clause
5679+ ///
5680+ /// Example:
5681+ /// ```sql
5682+ /// INSERT (product, quantity) VALUES(product, quantity)
5683+ /// ```
5684+ Insert ( MergeInsertExpr ) ,
5685+ /// An `UPDATE` clause
5686+ ///
5687+ /// Example:
5688+ /// ```sql
5689+ /// UPDATE SET quantity = T.quantity + S.quantity
5690+ /// ```
5691+ Update { assignments : Vec < Assignment > } ,
5692+ /// A plain `DELETE` clause
5693+ Delete ,
5694+ }
5695+
5696+ impl Display for MergeAction {
5697+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
5698+ match self {
5699+ MergeAction :: Insert ( insert) => {
5700+ write ! ( f, "INSERT {insert}" )
5701+ }
5702+ MergeAction :: Update { assignments } => {
5703+ write ! ( f, "UPDATE SET {}" , display_comma_separated( assignments) )
5704+ }
5705+ MergeAction :: Delete => {
5706+ write ! ( f, "DELETE" )
56165707 }
56175708 }
56185709 }
56195710}
56205711
5712+ /// A when clause within a `MERGE` Statement
5713+ ///
5714+ /// Example:
5715+ /// ```sql
5716+ /// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
5717+ /// ```
5718+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
5719+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
5720+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
5721+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
5722+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
5723+ pub struct MergeClause {
5724+ pub clause_kind : MergeClauseKind ,
5725+ pub predicate : Option < Expr > ,
5726+ pub action : MergeAction ,
5727+ }
5728+
5729+ impl Display for MergeClause {
5730+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
5731+ let MergeClause {
5732+ clause_kind,
5733+ predicate,
5734+ action,
5735+ } = self ;
5736+
5737+ write ! ( f, "WHEN {clause_kind}" ) ?;
5738+ if let Some ( pred) = predicate {
5739+ write ! ( f, " AND {pred}" ) ?;
5740+ }
5741+ write ! ( f, " THEN {action}" )
5742+ }
5743+ }
5744+
56215745#[ derive( Debug , Copy , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
56225746#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
56235747#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
0 commit comments