@@ -33,7 +33,8 @@ use super::{
3333 display_comma_separated, helpers:: attached_token:: AttachedToken , query:: InputFormatClause ,
3434 Assignment , Expr , FromTable , Ident , InsertAliases , MysqlInsertPriority , ObjectName , OnInsert ,
3535 OptimizerHint , OrderByExpr , Query , SelectInto , SelectItem , Setting , SqliteOnConflict ,
36- TableFactor , TableObject , TableWithJoins , UpdateTableFromKind , Values ,
36+ TableAliasWithoutColumns , TableFactor , TableObject , TableWithJoins , UpdateTableFromKind ,
37+ Values ,
3738} ;
3839
3940/// INSERT statement.
@@ -43,11 +44,11 @@ use super::{
4344pub struct Insert {
4445 /// Token for the `INSERT` keyword (or its substitutes)
4546 pub insert_token : AttachedToken ,
46- /// A query optimizer hint
47+ /// Query optimizer hints
4748 ///
4849 /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html)
4950 /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
50- pub optimizer_hint : Option < OptimizerHint > ,
51+ pub optimizer_hints : Vec < OptimizerHint > ,
5152 /// Only for Sqlite
5253 pub or : Option < SqliteOnConflict > ,
5354 /// Only for mysql
@@ -56,10 +57,11 @@ pub struct Insert {
5657 pub into : bool ,
5758 /// TABLE
5859 pub table : TableObject ,
59- /// table_name as foo (for PostgreSQL)
60- pub table_alias : Option < Ident > ,
60+ /// `table_name as foo` (for PostgreSQL)
61+ /// `table_name foo` (for Oracle)
62+ pub table_alias : Option < TableAliasWithoutColumns > ,
6163 /// COLUMNS
62- pub columns : Vec < Ident > ,
64+ pub columns : Vec < ObjectName > ,
6365 /// Overwrite (Hive)
6466 pub overwrite : bool ,
6567 /// A SQL query that specifies what to insert
@@ -77,6 +79,9 @@ pub struct Insert {
7779 pub on : Option < OnInsert > ,
7880 /// RETURNING
7981 pub returning : Option < Vec < SelectItem > > ,
82+ /// OUTPUT (MSSQL)
83+ /// See <https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql>
84+ pub output : Option < OutputClause > ,
8085 /// Only for mysql
8186 pub replace_into : bool ,
8287 /// Only for mysql
@@ -125,15 +130,20 @@ pub struct Insert {
125130impl Display for Insert {
126131 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
127132 // SQLite OR conflict has a special format: INSERT OR ... INTO table_name
128- let table_name = if let Some ( alias) = & self . table_alias {
129- format ! ( "{0} AS {alias}" , self . table)
133+ let table_name = if let Some ( table_alias) = & self . table_alias {
134+ format ! (
135+ "{table} {as_keyword}{alias}" ,
136+ table = self . table,
137+ as_keyword = if table_alias. explicit { "AS " } else { "" } ,
138+ alias = table_alias. alias
139+ )
130140 } else {
131141 self . table . to_string ( )
132142 } ;
133143
134144 if let Some ( on_conflict) = self . or {
135145 f. write_str ( "INSERT" ) ?;
136- if let Some ( hint) = self . optimizer_hint . as_ref ( ) {
146+ for hint in & self . optimizer_hints {
137147 write ! ( f, " {hint}" ) ?;
138148 }
139149 write ! ( f, " {on_conflict} INTO {table_name} " ) ?;
@@ -147,7 +157,7 @@ impl Display for Insert {
147157 "INSERT"
148158 }
149159 ) ?;
150- if let Some ( hint) = self . optimizer_hint . as_ref ( ) {
160+ for hint in & self . optimizer_hints {
151161 write ! ( f, " {hint}" ) ?;
152162 }
153163 if let Some ( priority) = self . priority {
@@ -196,6 +206,11 @@ impl Display for Insert {
196206 SpaceOrNewline . fmt ( f) ?;
197207 }
198208
209+ if let Some ( output) = & self . output {
210+ write ! ( f, "{output}" ) ?;
211+ SpaceOrNewline . fmt ( f) ?;
212+ }
213+
199214 if let Some ( settings) = & self . settings {
200215 write ! ( f, "SETTINGS {}" , display_comma_separated( settings) ) ?;
201216 SpaceOrNewline . fmt ( f) ?;
@@ -267,11 +282,11 @@ impl Display for Insert {
267282pub struct Delete {
268283 /// Token for the `DELETE` keyword
269284 pub delete_token : AttachedToken ,
270- /// A query optimizer hint
285+ /// Query optimizer hints
271286 ///
272287 /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html)
273288 /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
274- pub optimizer_hint : Option < OptimizerHint > ,
289+ pub optimizer_hints : Vec < OptimizerHint > ,
275290 /// Multi tables delete are supported in mysql
276291 pub tables : Vec < ObjectName > ,
277292 /// FROM
@@ -282,6 +297,9 @@ pub struct Delete {
282297 pub selection : Option < Expr > ,
283298 /// RETURNING
284299 pub returning : Option < Vec < SelectItem > > ,
300+ /// OUTPUT (MSSQL)
301+ /// See <https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql>
302+ pub output : Option < OutputClause > ,
285303 /// ORDER BY (MySQL)
286304 pub order_by : Vec < OrderByExpr > ,
287305 /// LIMIT (MySQL)
@@ -291,7 +309,7 @@ pub struct Delete {
291309impl Display for Delete {
292310 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
293311 f. write_str ( "DELETE" ) ?;
294- if let Some ( hint) = self . optimizer_hint . as_ref ( ) {
312+ for hint in & self . optimizer_hints {
295313 f. write_str ( " " ) ?;
296314 hint. fmt ( f) ?;
297315 }
@@ -307,6 +325,10 @@ impl Display for Delete {
307325 indented_list ( f, from) ?;
308326 }
309327 }
328+ if let Some ( output) = & self . output {
329+ SpaceOrNewline . fmt ( f) ?;
330+ write ! ( f, "{output}" ) ?;
331+ }
310332 if let Some ( using) = & self . using {
311333 SpaceOrNewline . fmt ( f) ?;
312334 f. write_str ( "USING" ) ?;
@@ -345,11 +367,11 @@ impl Display for Delete {
345367pub struct Update {
346368 /// Token for the `UPDATE` keyword
347369 pub update_token : AttachedToken ,
348- /// A query optimizer hint
370+ /// Query optimizer hints
349371 ///
350372 /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html)
351373 /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
352- pub optimizer_hint : Option < OptimizerHint > ,
374+ pub optimizer_hints : Vec < OptimizerHint > ,
353375 /// TABLE
354376 pub table : TableWithJoins ,
355377 /// Column assignments
@@ -360,6 +382,9 @@ pub struct Update {
360382 pub selection : Option < Expr > ,
361383 /// RETURNING
362384 pub returning : Option < Vec < SelectItem > > ,
385+ /// OUTPUT (MSSQL)
386+ /// See <https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql>
387+ pub output : Option < OutputClause > ,
363388 /// SQLite-specific conflict resolution clause
364389 pub or : Option < SqliteOnConflict > ,
365390 /// LIMIT
@@ -368,11 +393,12 @@ pub struct Update {
368393
369394impl Display for Update {
370395 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
371- f. write_str ( "UPDATE " ) ?;
372- if let Some ( hint) = self . optimizer_hint . as_ref ( ) {
373- hint. fmt ( f) ?;
396+ f. write_str ( "UPDATE" ) ?;
397+ for hint in & self . optimizer_hints {
374398 f. write_str ( " " ) ?;
399+ hint. fmt ( f) ?;
375400 }
401+ f. write_str ( " " ) ?;
376402 if let Some ( or) = & self . or {
377403 or. fmt ( f) ?;
378404 f. write_str ( " " ) ?;
@@ -388,6 +414,10 @@ impl Display for Update {
388414 f. write_str ( "SET" ) ?;
389415 indented_list ( f, & self . assignments ) ?;
390416 }
417+ if let Some ( output) = & self . output {
418+ SpaceOrNewline . fmt ( f) ?;
419+ write ! ( f, "{output}" ) ?;
420+ }
391421 if let Some ( UpdateTableFromKind :: AfterSet ( from) ) = & self . from {
392422 SpaceOrNewline . fmt ( f) ?;
393423 f. write_str ( "FROM" ) ?;
@@ -419,10 +449,10 @@ impl Display for Update {
419449pub struct Merge {
420450 /// The `MERGE` token that starts the statement.
421451 pub merge_token : AttachedToken ,
422- /// A query optimizer hint
452+ /// Query optimizer hints
423453 ///
424454 /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
425- pub optimizer_hint : Option < OptimizerHint > ,
455+ pub optimizer_hints : Vec < OptimizerHint > ,
426456 /// optional INTO keyword
427457 pub into : bool ,
428458 /// Specifies the table to merge
@@ -440,7 +470,7 @@ pub struct Merge {
440470impl Display for Merge {
441471 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
442472 f. write_str ( "MERGE" ) ?;
443- if let Some ( hint) = self . optimizer_hint . as_ref ( ) {
473+ for hint in & self . optimizer_hints {
444474 write ! ( f, " {hint}" ) ?;
445475 }
446476 if self . into {
@@ -709,11 +739,11 @@ impl Display for MergeUpdateExpr {
709739 }
710740}
711741
712- /// A `OUTPUT` Clause in the end of a `MERGE` Statement
742+ /// An `OUTPUT` clause on `MERGE`, `INSERT`, `UPDATE`, or `DELETE` (MSSQL).
713743///
714744/// Example:
715745/// OUTPUT $action, deleted.* INTO dbo.temp_products;
716- /// [mssql]( https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
746+ /// < https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql>
717747#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
718748#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
719749#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
0 commit comments