@@ -101,6 +101,22 @@ pub enum TableConstraint {
101101 /// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-natural-language.html
102102 /// [2]: https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html
103103 FulltextOrSpatial ( FullTextOrSpatialConstraint ) ,
104+ /// PostgreSQL [definition][1] for promoting an existing unique index to a
105+ /// `PRIMARY KEY` constraint:
106+ ///
107+ /// `[ CONSTRAINT constraint_name ] PRIMARY KEY USING INDEX index_name
108+ /// [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
109+ ///
110+ /// [1]: https://www.postgresql.org/docs/current/sql-altertable.html
111+ PrimaryKeyUsingIndex ( ConstraintUsingIndex ) ,
112+ /// PostgreSQL [definition][1] for promoting an existing unique index to a
113+ /// `UNIQUE` constraint:
114+ ///
115+ /// `[ CONSTRAINT constraint_name ] UNIQUE USING INDEX index_name
116+ /// [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
117+ ///
118+ /// [1]: https://www.postgresql.org/docs/current/sql-altertable.html
119+ UniqueUsingIndex ( ConstraintUsingIndex ) ,
104120}
105121
106122impl From < UniqueConstraint > for TableConstraint {
@@ -148,6 +164,8 @@ impl fmt::Display for TableConstraint {
148164 TableConstraint :: Check ( constraint) => constraint. fmt ( f) ,
149165 TableConstraint :: Index ( constraint) => constraint. fmt ( f) ,
150166 TableConstraint :: FulltextOrSpatial ( constraint) => constraint. fmt ( f) ,
167+ TableConstraint :: PrimaryKeyUsingIndex ( c) => c. fmt_with_keyword ( f, "PRIMARY KEY" ) ,
168+ TableConstraint :: UniqueUsingIndex ( c) => c. fmt_with_keyword ( f, "UNIQUE" ) ,
151169 }
152170 }
153171}
@@ -535,3 +553,53 @@ impl crate::ast::Spanned for UniqueConstraint {
535553 )
536554 }
537555}
556+
557+ /// PostgreSQL constraint that promotes an existing unique index to a table constraint.
558+ ///
559+ /// `[ CONSTRAINT constraint_name ] { UNIQUE | PRIMARY KEY } USING INDEX index_name
560+ /// [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
561+ ///
562+ /// See <https://www.postgresql.org/docs/current/sql-altertable.html>
563+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
564+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
565+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
566+ pub struct ConstraintUsingIndex {
567+ /// Optional constraint name.
568+ pub name : Option < Ident > ,
569+ /// The name of the existing unique index to promote.
570+ pub index_name : Ident ,
571+ /// Optional characteristics like `DEFERRABLE`.
572+ pub characteristics : Option < ConstraintCharacteristics > ,
573+ }
574+
575+ impl ConstraintUsingIndex {
576+ /// Format as `[CONSTRAINT name] <keyword> USING INDEX index_name [characteristics]`.
577+ pub fn fmt_with_keyword ( & self , f : & mut fmt:: Formatter , keyword : & str ) -> fmt:: Result {
578+ use crate :: ast:: ddl:: { display_constraint_name, display_option_spaced} ;
579+ write ! (
580+ f,
581+ "{}{} USING INDEX {}" ,
582+ display_constraint_name( & self . name) ,
583+ keyword,
584+ self . index_name,
585+ ) ?;
586+ write ! ( f, "{}" , display_option_spaced( & self . characteristics) ) ?;
587+ Ok ( ( ) )
588+ }
589+ }
590+
591+ impl crate :: ast:: Spanned for ConstraintUsingIndex {
592+ fn span ( & self ) -> Span {
593+ let start = self
594+ . name
595+ . as_ref ( )
596+ . map ( |i| i. span )
597+ . unwrap_or ( self . index_name . span ) ;
598+ let end = self
599+ . characteristics
600+ . as_ref ( )
601+ . map ( |c| c. span ( ) )
602+ . unwrap_or ( self . index_name . span ) ;
603+ start. union ( & end)
604+ }
605+ }
0 commit comments