@@ -248,8 +248,7 @@ impl ExportContext {
248248 }
249249}
250250
251- #[ derive( Default ) ]
252- pub struct Factory { }
251+ struct TargetFactory ;
253252
254253#[ derive( Debug , Clone , Serialize , Deserialize , PartialEq , Eq , Hash ) ]
255254pub struct TableId {
@@ -614,7 +613,7 @@ impl SetupChange {
614613}
615614
616615#[ async_trait]
617- impl TargetFactoryBase for Factory {
616+ impl TargetFactoryBase for TargetFactory {
618617 type Spec = Spec ;
619618 type DeclarationSpec = ( ) ;
620619 type SetupState = SetupState ;
@@ -752,3 +751,123 @@ impl TargetFactoryBase for Factory {
752751 Ok ( ( ) )
753752 }
754753}
754+
755+ ////////////////////////////////////////////////////////////
756+ // Attachment Factory
757+ ////////////////////////////////////////////////////////////
758+
759+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
760+ pub struct SqlStatementAttachmentSpec {
761+ name : String ,
762+ setup_sql : String ,
763+ teardown_sql : Option < String > ,
764+ }
765+
766+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
767+ pub struct SqlStatementAttachmentState {
768+ setup_sql : String ,
769+ teardown_sql : Option < String > ,
770+ }
771+
772+ pub struct SqlStatementAttachmentSetupChange {
773+ db_pool : PgPool ,
774+ setup_sql_to_run : Option < String > ,
775+ teardown_sql_to_run : IndexSet < String > ,
776+ }
777+
778+ #[ async_trait]
779+ impl AttachmentSetupChange for SqlStatementAttachmentSetupChange {
780+ fn describe_changes ( & self ) -> Vec < String > {
781+ let mut result = vec ! [ ] ;
782+ for teardown_sql in self . teardown_sql_to_run . iter ( ) {
783+ result. push ( format ! ( "Run teardown SQL: {}" , teardown_sql) ) ;
784+ }
785+ if let Some ( setup_sql) = & self . setup_sql_to_run {
786+ result. push ( format ! ( "Run setup SQL: {}" , setup_sql) ) ;
787+ }
788+ result
789+ }
790+
791+ async fn apply_change ( & self ) -> Result < ( ) > {
792+ for teardown_sql in self . teardown_sql_to_run . iter ( ) {
793+ sqlx:: query ( teardown_sql) . execute ( & self . db_pool ) . await ?;
794+ }
795+ if let Some ( setup_sql) = & self . setup_sql_to_run {
796+ sqlx:: query ( setup_sql) . execute ( & self . db_pool ) . await ?;
797+ }
798+ Ok ( ( ) )
799+ }
800+ }
801+
802+ struct SqlAttachmentFactory ;
803+
804+ #[ async_trait]
805+ impl TargetSpecificAttachmentFactoryBase for SqlAttachmentFactory {
806+ type TargetKey = TableId ;
807+ type TargetSpec = Spec ;
808+ type Spec = SqlStatementAttachmentSpec ;
809+ type SetupKey = String ;
810+ type SetupState = SqlStatementAttachmentState ;
811+ type SetupChange = SqlStatementAttachmentSetupChange ;
812+
813+ fn name ( & self ) -> & str {
814+ "PostgresSqlAttachment"
815+ }
816+
817+ fn get_state (
818+ & self ,
819+ _target_name : & str ,
820+ _target_spec : & Spec ,
821+ attachment_spec : SqlStatementAttachmentSpec ,
822+ ) -> Result < TypedTargetAttachmentState < Self > > {
823+ Ok ( TypedTargetAttachmentState {
824+ setup_key : attachment_spec. name ,
825+ setup_state : SqlStatementAttachmentState {
826+ setup_sql : attachment_spec. setup_sql ,
827+ teardown_sql : attachment_spec. teardown_sql ,
828+ } ,
829+ } )
830+ }
831+
832+ async fn diff_setup_states (
833+ & self ,
834+ target_key : & TableId ,
835+ _attachment_key : & String ,
836+ new_state : Option < SqlStatementAttachmentState > ,
837+ existing_states : setup:: CombinedState < SqlStatementAttachmentState > ,
838+ context : & interface:: FlowInstanceContext ,
839+ ) -> Result < Option < SqlStatementAttachmentSetupChange > > {
840+ let teardown_sql_to_run: IndexSet < String > = if new_state. is_none ( ) {
841+ existing_states
842+ . possible_versions ( )
843+ . filter_map ( |s| s. teardown_sql . clone ( ) )
844+ . collect ( )
845+ } else {
846+ IndexSet :: new ( )
847+ } ;
848+ let setup_sql_to_run = if let Some ( new_state) = new_state
849+ && !existing_states. always_exists_and ( |s| s. setup_sql == new_state. setup_sql )
850+ {
851+ Some ( new_state. setup_sql )
852+ } else {
853+ None
854+ } ;
855+ let change = if setup_sql_to_run. is_some ( ) || !teardown_sql_to_run. is_empty ( ) {
856+ let db_pool = get_db_pool ( target_key. database . as_ref ( ) , & context. auth_registry ) . await ?;
857+ Some ( SqlStatementAttachmentSetupChange {
858+ db_pool,
859+ setup_sql_to_run,
860+ teardown_sql_to_run,
861+ } )
862+ } else {
863+ None
864+ } ;
865+ Ok ( change)
866+ }
867+ }
868+
869+ pub fn register ( registry : & mut ExecutorFactoryRegistry ) -> Result < ( ) > {
870+ TargetFactory . register ( registry) ?;
871+ SqlAttachmentFactory . register ( registry) ?;
872+ Ok ( ( ) )
873+ }
0 commit comments