@@ -24,7 +24,9 @@ use serde::{Deserialize, Serialize};
24
24
use sqlparser_derive:: { Visit , VisitMut } ;
25
25
26
26
use 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
+ } ;
28
30
use crate :: tokenizer:: Token ;
29
31
30
32
/// An `ALTER TABLE` (`Statement::AlterTable`) operation
@@ -575,6 +577,13 @@ pub enum ColumnOption {
575
577
CharacterSet ( ObjectName ) ,
576
578
Comment ( String ) ,
577
579
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
+ } ,
578
587
}
579
588
580
589
impl fmt:: Display for ColumnOption {
@@ -610,10 +619,63 @@ impl fmt::Display for ColumnOption {
610
619
CharacterSet ( n) => write ! ( f, "CHARACTER SET {n}" ) ,
611
620
Comment ( v) => write ! ( f, "COMMENT '{}'" , escape_single_quote_string( v) ) ,
612
621
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
+ } ,
613
664
}
614
665
}
615
666
}
616
667
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
+
617
679
fn display_constraint_name ( name : & ' _ Option < Ident > ) -> impl fmt:: Display + ' _ {
618
680
struct ConstraintName < ' a > ( & ' a Option < Ident > ) ;
619
681
impl < ' a > fmt:: Display for ConstraintName < ' a > {
0 commit comments