@@ -101,6 +101,14 @@ 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` or `UNIQUE` constraint:
106+ ///
107+ /// `[ CONSTRAINT constraint_name ] { UNIQUE | 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+ ConstraintUsingIndex ( ConstraintUsingIndex ) ,
104112}
105113
106114impl From < UniqueConstraint > for TableConstraint {
@@ -139,6 +147,12 @@ impl From<FullTextOrSpatialConstraint> for TableConstraint {
139147 }
140148}
141149
150+ impl From < ConstraintUsingIndex > for TableConstraint {
151+ fn from ( constraint : ConstraintUsingIndex ) -> Self {
152+ TableConstraint :: ConstraintUsingIndex ( constraint)
153+ }
154+ }
155+
142156impl fmt:: Display for TableConstraint {
143157 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
144158 match self {
@@ -148,6 +162,7 @@ impl fmt::Display for TableConstraint {
148162 TableConstraint :: Check ( constraint) => constraint. fmt ( f) ,
149163 TableConstraint :: Index ( constraint) => constraint. fmt ( f) ,
150164 TableConstraint :: FulltextOrSpatial ( constraint) => constraint. fmt ( f) ,
165+ TableConstraint :: ConstraintUsingIndex ( constraint) => constraint. fmt ( f) ,
151166 }
152167 }
153168}
@@ -535,3 +550,58 @@ impl crate::ast::Spanned for UniqueConstraint {
535550 )
536551 }
537552}
553+
554+ /// PostgreSQL constraint that promotes an existing unique index to a table constraint.
555+ ///
556+ /// `[ CONSTRAINT constraint_name ] { UNIQUE | PRIMARY KEY } USING INDEX index_name
557+ /// [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
558+ ///
559+ /// See <https://www.postgresql.org/docs/current/sql-altertable.html>
560+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
561+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
562+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
563+ pub struct ConstraintUsingIndex {
564+ /// Optional constraint name.
565+ pub name : Option < Ident > ,
566+ /// Whether this is a `PRIMARY KEY` (true) or `UNIQUE` (false) constraint.
567+ pub is_primary_key : bool ,
568+ /// The name of the existing unique index to promote.
569+ pub index_name : Ident ,
570+ /// Optional characteristics like `DEFERRABLE`.
571+ pub characteristics : Option < ConstraintCharacteristics > ,
572+ }
573+
574+ impl fmt:: Display for ConstraintUsingIndex {
575+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
576+ use crate :: ast:: ddl:: { display_constraint_name, display_option_spaced} ;
577+ write ! (
578+ f,
579+ "{}{} USING INDEX {}" ,
580+ display_constraint_name( & self . name) ,
581+ if self . is_primary_key {
582+ "PRIMARY KEY"
583+ } else {
584+ "UNIQUE"
585+ } ,
586+ self . index_name,
587+ ) ?;
588+ write ! ( f, "{}" , display_option_spaced( & self . characteristics) ) ?;
589+ Ok ( ( ) )
590+ }
591+ }
592+
593+ impl crate :: ast:: Spanned for ConstraintUsingIndex {
594+ fn span ( & self ) -> Span {
595+ let start = self
596+ . name
597+ . as_ref ( )
598+ . map ( |i| i. span )
599+ . unwrap_or ( self . index_name . span ) ;
600+ let end = self
601+ . characteristics
602+ . as_ref ( )
603+ . map ( |c| c. span ( ) )
604+ . unwrap_or ( self . index_name . span ) ;
605+ start. union ( & end)
606+ }
607+ }
0 commit comments