@@ -24,7 +24,9 @@ use serde::{Deserialize, Serialize};
2424use sqlparser_derive:: { Visit , VisitMut } ;
2525
2626use crate :: ast:: value:: escape_single_quote_string;
27- use crate :: ast:: { display_comma_separated, display_separated, DataType , Expr , Ident , ObjectName } ;
27+ use crate :: ast:: {
28+ display_comma_separated, display_separated, DataType , Expr , Ident , ObjectName , SequenceOptions ,
29+ } ;
2830use crate :: tokenizer:: Token ;
2931
3032/// An `ALTER TABLE` (`Statement::AlterTable`) operation
@@ -575,6 +577,13 @@ pub enum ColumnOption {
575577 CharacterSet ( ObjectName ) ,
576578 Comment ( String ) ,
577579 OnUpdate ( Expr ) ,
580+ /// `Generated`s are modifiers that follow a column definition in a `CREATE
581+ /// TABLE` statement.
582+ Generated {
583+ generated_as : GeneratedAs ,
584+ sequence_options : Option < Vec < SequenceOptions > > ,
585+ generation_expr : Option < Expr > ,
586+ } ,
578587}
579588
580589impl fmt:: Display for ColumnOption {
@@ -610,10 +619,63 @@ impl fmt::Display for ColumnOption {
610619 CharacterSet ( n) => write ! ( f, "CHARACTER SET {n}" ) ,
611620 Comment ( v) => write ! ( f, "COMMENT '{}'" , escape_single_quote_string( v) ) ,
612621 OnUpdate ( expr) => write ! ( f, "ON UPDATE {expr}" ) ,
622+ Generated {
623+ generated_as,
624+ sequence_options,
625+ generation_expr,
626+ } => match generated_as {
627+ GeneratedAs :: Always => {
628+ write ! ( f, "GENERATED ALWAYS AS IDENTITY" ) ?;
629+ if sequence_options. is_some ( ) {
630+ let so = sequence_options. as_ref ( ) . unwrap ( ) ;
631+ if !so. is_empty ( ) {
632+ write ! ( f, " (" ) ?;
633+ }
634+ for sequence_option in so {
635+ write ! ( f, "{sequence_option}" ) ?;
636+ }
637+ if !so. is_empty ( ) {
638+ write ! ( f, " )" ) ?;
639+ }
640+ }
641+ Ok ( ( ) )
642+ }
643+ GeneratedAs :: ByDefault => {
644+ write ! ( f, "GENERATED BY DEFAULT AS IDENTITY" ) ?;
645+ if sequence_options. is_some ( ) {
646+ let so = sequence_options. as_ref ( ) . unwrap ( ) ;
647+ if !so. is_empty ( ) {
648+ write ! ( f, " (" ) ?;
649+ }
650+ for sequence_option in so {
651+ write ! ( f, "{sequence_option}" ) ?;
652+ }
653+ if !so. is_empty ( ) {
654+ write ! ( f, " )" ) ?;
655+ }
656+ }
657+ Ok ( ( ) )
658+ }
659+ GeneratedAs :: ExpStored => {
660+ let expr = generation_expr. as_ref ( ) . unwrap ( ) ;
661+ write ! ( f, "GENERATED ALWAYS AS ({expr}) STORED" )
662+ }
663+ } ,
613664 }
614665 }
615666}
616667
668+ /// `GeneratedAs`s are modifiers that follow a column option in a `generated`.
669+ /// 'ExpStored' is PostgreSQL specific
670+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
671+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
672+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
673+ pub enum GeneratedAs {
674+ Always ,
675+ ByDefault ,
676+ ExpStored ,
677+ }
678+
617679fn display_constraint_name ( name : & ' _ Option < Ident > ) -> impl fmt:: Display + ' _ {
618680 struct ConstraintName < ' a > ( & ' a Option < Ident > ) ;
619681 impl < ' a > fmt:: Display for ConstraintName < ' a > {
0 commit comments