module Sqel.Data.Migration where import Exon (exon) import Generics.SOP (NP (Nil, (:*))) import Hasql.Encoders (Params) import Sqel.Data.Dd ((:>) ((:>))) import Sqel.Data.PgType (ColumnType, PgColumnName, PgColumns, PgTable) import Sqel.Data.PgTypeName (PgCompName, PgTableName, PgTypeName) data ColumnAction where AddColumn :: PgColumnName -> ColumnType -> Maybe (a, Params a) -> ColumnAction RemoveColumn :: PgColumnName -> ColumnType -> ColumnAction RenameColumn :: PgColumnName -> PgColumnName -> ColumnAction RenameColumnType :: PgColumnName -> PgCompName -> ColumnAction instance Show ColumnAction where showsPrec :: Int -> ColumnAction -> ShowS showsPrec Int d = Bool -> ShowS -> ShowS showParen (Int d forall a. Ord a => a -> a -> Bool > Int 10) forall b c a. (b -> c) -> (a -> b) -> a -> c . \case AddColumn PgColumnName name ColumnType tpe Maybe (a, Params a) _ -> [exon|AddColumn #{showsPrec 11 name} #{showsPrec 11 tpe}|] RemoveColumn PgColumnName name ColumnType tpe -> [exon|RemoveColumn #{showsPrec 11 name} #{showsPrec 11 tpe}|] RenameColumn PgColumnName old PgColumnName new -> [exon|RenameColumn #{showsPrec 11 old} #{showsPrec 11 new}|] RenameColumnType PgColumnName name PgCompName new -> [exon|RenameColumnType #{showsPrec 11 name} #{showsPrec 11 new}|] data TypeAction (table :: Bool) where ModifyAction :: PgTypeName table -> [ColumnAction] -> TypeAction table RenameAction :: PgCompName -> [ColumnAction] -> TypeAction 'False AddAction :: PgColumns -> TypeAction 'False type TableAction = TypeAction 'True type CompAction = TypeAction 'False data MigrationActions ext = AutoActions { forall ext. MigrationActions ext -> TableAction table :: TableAction, forall ext. MigrationActions ext -> Map PgCompName CompAction types :: Map PgCompName CompAction } | CustomActions ext deriving stock (forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall ext x. Rep (MigrationActions ext) x -> MigrationActions ext forall ext x. MigrationActions ext -> Rep (MigrationActions ext) x $cto :: forall ext x. Rep (MigrationActions ext) x -> MigrationActions ext $cfrom :: forall ext x. MigrationActions ext -> Rep (MigrationActions ext) x Generic) data Mig = Mig { Mig -> * from :: Type, Mig -> * to :: Type, Mig -> * -> * effect :: Type -> Type, Mig -> * ext :: Type } type Migration :: Mig -> Type data Migration t where Migration :: { forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> PgTable from tableFrom :: PgTable from, forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> PgTable to tableTo :: PgTable to, forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> MigrationActions ext actions :: MigrationActions ext } -> Migration ('Mig from to m ext) type family MigFrom (mig :: Mig) :: Type where MigFrom ('Mig from _ _ _) = from type family MigTo (mig :: Mig) :: Type where MigTo ('Mig _ to _ _) = to type family MigEff (mig :: Mig) :: Type -> Type where MigEff ('Mig _ _ m _) = m type family MigExt (mig :: Mig) :: Type where MigExt ('Mig _ _ _ ext) = ext type UniMigList :: (Type -> Type) -> Type -> [Type] -> [Mig] type family UniMigList m ext as where UniMigList _ _ '[] = '[] UniMigList m ext [new, old] = '[ 'Mig old new m ext] UniMigList m ext (new : old : as) = 'Mig old new m ext : UniMigList m ext (old : as) type UniMigs :: (Type -> Type) -> Type -> [Type] -> Type -> [Mig] type family UniMigs m ext old cur where UniMigs _ _ '[] _ = '[] UniMigs m ext '[o] cur = '[ 'Mig o cur m ext] UniMigs m ext (o : os) cur = 'Mig o cur m ext : UniMigList m ext (o : os) type Migrations :: (Type -> Type) -> [Mig] -> Type newtype Migrations m migs = Migrations { forall (m :: * -> *) (migs :: [Mig]). Migrations m migs -> NP Migration migs unMigrations :: NP Migration migs } type UniMigrations m ext old cur = Migrations m (UniMigs m ext old cur) type AutoMigrations m old cur = UniMigrations m Void old cur class MkMigrations arg migs | arg -> migs, migs -> arg where mkMigrations :: arg -> NP Migration migs instance ( MkMigrations old (mig1 : migs) ) => MkMigrations (Migration ('Mig from to m ext) :> old) ('Mig from to m ext : mig1 : migs) where mkMigrations :: (Migration ('Mig from to m ext) :> old) -> NP Migration ('Mig from to m ext : mig1 : migs) mkMigrations (Migration ('Mig from to m ext) next :> old old) = Migration ('Mig from to m ext) next forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) :* forall arg (migs :: [Mig]). MkMigrations arg migs => arg -> NP Migration migs mkMigrations old old instance MkMigrations (Migration ('Mig from to m ext)) '[ 'Mig from to m ext] where mkMigrations :: Migration ('Mig from to m ext) -> NP Migration '[ 'Mig from to m ext] mkMigrations Migration ('Mig from to m ext) next = Migration ('Mig from to m ext) next forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) :* forall {k} (a :: k -> *). NP a '[] Nil migrate :: MkMigrations arg migs => arg -> Migrations m migs migrate :: forall arg (migs :: [Mig]) (m :: * -> *). MkMigrations arg migs => arg -> Migrations m migs migrate = forall (m :: * -> *) (migs :: [Mig]). NP Migration migs -> Migrations m migs Migrations forall b c a. (b -> c) -> (a -> b) -> a -> c . forall arg (migs :: [Mig]). MkMigrations arg migs => arg -> NP Migration migs mkMigrations noMigrations :: Migrations m '[] noMigrations :: forall (m :: * -> *). Migrations m '[] noMigrations = forall (m :: * -> *) (migs :: [Mig]). NP Migration migs -> Migrations m migs Migrations forall {k} (a :: k -> *). NP a '[] Nil class CustomMigration m mig where customTypeKeys :: MigExt mig -> m (Set (PgCompName, Bool)) customMigration :: PgTableName -> Set PgCompName -> MigExt mig -> m () instance CustomMigration m ('Mig from to m Void) where customTypeKeys :: MigExt ('Mig from to m Void) -> m (Set (PgCompName, Bool)) customTypeKeys = MigExt ('Mig from to m Void) -> m (Set (PgCompName, Bool)) \case customMigration :: PgTableName -> Set PgCompName -> MigExt ('Mig from to m Void) -> m () customMigration PgTableName _ Set PgCompName _ = MigExt ('Mig from to m Void) -> m () \case class HoistMigration m n ext ext' | m n ext -> ext' where hoistMigration :: (∀ x . m x -> n x) -> ext -> ext' instance HoistMigration m n Void Void where hoistMigration :: (forall (x :: k). m x -> n x) -> Void -> Void hoistMigration forall (x :: k). m x -> n x _ = Void -> Void \case class HoistMigrations m n migs migs' | m n migs -> migs' where hoistMigrations :: (∀ x . m x -> n x) -> Migrations m migs -> Migrations n migs' instance HoistMigrations m n '[] '[] where hoistMigrations :: (forall x. m x -> n x) -> Migrations m '[] -> Migrations n '[] hoistMigrations forall x. m x -> n x _ Migrations {NP Migration '[] unMigrations :: NP Migration '[] $sel:unMigrations:Migrations :: forall (m :: * -> *) (migs :: [Mig]). Migrations m migs -> NP Migration migs ..} = Migrations {NP Migration '[] unMigrations :: NP Migration '[] $sel:unMigrations:Migrations :: NP Migration '[] ..} instance ( HoistMigration m n ext ext', HoistMigrations m n migs migs' ) => HoistMigrations m n ('Mig from to m ext : migs) ('Mig from to n ext' : migs') where hoistMigrations :: (forall x. m x -> n x) -> Migrations m ('Mig from to m ext : migs) -> Migrations n ('Mig from to n ext' : migs') hoistMigrations forall x. m x -> n x f (Migrations (Migration {PgTable from PgTable to MigrationActions ext actions :: MigrationActions ext tableTo :: PgTable to tableFrom :: PgTable from $sel:actions:Migration :: forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> MigrationActions ext $sel:tableTo:Migration :: forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> PgTable to $sel:tableFrom:Migration :: forall from to ext (m :: * -> *). Migration ('Mig from to m ext) -> PgTable from ..} :* NP Migration xs migs)) = forall (m :: * -> *) (migs :: [Mig]). NP Migration migs -> Migrations m migs Migrations (Migration {$sel:actions:Migration :: MigrationActions ext' actions = MigrationActions ext -> MigrationActions ext' hoistAction MigrationActions ext actions, PgTable from PgTable to tableTo :: PgTable to tableFrom :: PgTable from $sel:tableTo:Migration :: PgTable to $sel:tableFrom:Migration :: PgTable from ..} forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) :* forall (m :: * -> *) (migs :: [Mig]). Migrations m migs -> NP Migration migs unMigrations (forall (m :: * -> *) (n :: * -> *) (migs :: [Mig]) (migs' :: [Mig]). HoistMigrations m n migs migs' => (forall x. m x -> n x) -> Migrations m migs -> Migrations n migs' hoistMigrations forall x. m x -> n x f (forall (m :: * -> *) (migs :: [Mig]). NP Migration migs -> Migrations m migs Migrations NP Migration xs migs))) where hoistAction :: MigrationActions ext -> MigrationActions ext' hoistAction = \case CustomActions ext ext -> forall ext. ext -> MigrationActions ext CustomActions (forall {k} (m :: k -> *) (n :: k -> *) ext ext'. HoistMigration m n ext ext' => (forall (x :: k). m x -> n x) -> ext -> ext' hoistMigration forall x. m x -> n x f ext ext) AutoActions {Map PgCompName CompAction TableAction types :: Map PgCompName CompAction table :: TableAction $sel:types:AutoActions :: forall ext. MigrationActions ext -> Map PgCompName CompAction $sel:table:AutoActions :: forall ext. MigrationActions ext -> TableAction ..} -> AutoActions {Map PgCompName CompAction TableAction types :: Map PgCompName CompAction table :: TableAction $sel:types:AutoActions :: Map PgCompName CompAction $sel:table:AutoActions :: TableAction ..}