sqel-0.0.1.0: lib/Sqel/Prim.hs
module Sqel.Prim where
import Data.Aeson (FromJSON, ToJSON)
import Generics.SOP (I (I), NP (Nil, (:*)))
import Sqel.Class.Mods (MapMod, SymNP, setMod, symMods)
import Sqel.Column (nullable)
import Sqel.Data.Dd (ConCol, Dd (Dd), DdK (DdK), DdStruct (DdPrim), DdType, Struct (Prim))
import Sqel.Data.MigrationParams (
MigrationDefault (MigrationDefault),
MigrationDelete (MigrationDelete),
MigrationRename (MigrationRename),
MigrationRenameType (MigrationRenameType),
)
import Sqel.Data.Mods (
ArrayColumn (ArrayColumn),
EnumColumn,
Ignore (Ignore),
Mods (Mods),
Newtype (Newtype),
pattern NoMods,
type NoMods,
Nullable,
ReadShowColumn,
)
import Sqel.Data.PgType (PgPrimName)
import Sqel.Data.Sel (
IndexName,
Sel (SelAuto, SelIndex, SelSymbol, SelUnused),
SelPrefix (DefaultPrefix),
SelW (SelWAuto, SelWIndex),
)
import Sqel.Mods (PrimValueCodec, primEnumMods, primJsonMods, primReadShowMods)
import Sqel.Names (named, selAs)
import Sqel.SOP.Constraint (ProductGCode)
import Sqel.SOP.Error (Quoted)
import Sqel.SOP.Newtype (UnwrapNewtype (unwrapNewtype, wrapNewtype))
type IndexColumnWith prefix name =
'DdK ('SelIndex prefix name) NoMods Int64 'Prim
type IndexColumn name =
IndexColumnWith 'DefaultPrefix name
column :: Mods p -> Dd ('DdK 'SelAuto p a 'Prim)
column m =
Dd SelWAuto m DdPrim
mods ::
SymNP p ps =>
p ->
Mods ps
mods =
symMods
primMod ::
p ->
Dd ('DdK 'SelAuto '[p] a 'Prim)
primMod p =
column (Mods (I p :* Nil))
primMods ::
SymNP p ps =>
p ->
Dd ('DdK 'SelAuto ps a 'Prim)
primMods p =
column (mods p)
prim ::
∀ a .
Dd ('DdK 'SelAuto NoMods a 'Prim)
prim =
column NoMods
ignore ::
∀ a .
Dd ('DdK 'SelUnused '[Ignore] a 'Prim)
ignore =
selAs (primMod Ignore)
type NewtypeError =
Quoted "primNewtype" <> " declares a column for a newtype using " <> Quoted "Generic" <> "."
primNewtype ::
∀ a w err .
err ~ NewtypeError =>
UnwrapNewtype err a w =>
Dd ('DdK 'SelAuto '[Newtype a w] a 'Prim)
primNewtype =
primMod (Newtype (unwrapNewtype @err) (wrapNewtype @err))
primCoerce ::
∀ a w .
Coercible a w =>
Dd ('DdK 'SelAuto '[Newtype a w] a 'Prim)
primCoerce =
primMod (Newtype coerce coerce)
primIndex ::
∀ tpe name .
IndexName 'DefaultPrefix tpe name =>
Dd (IndexColumn tpe)
primIndex =
Dd (SelWIndex Proxy) NoMods DdPrim
-- TODO move aeson to reify
json ::
∀ a .
ToJSON a =>
FromJSON a =>
Dd ('DdK 'SelAuto [PgPrimName, PrimValueCodec a] a 'Prim)
json =
column primJsonMods
enum ::
∀ a .
Dd ('DdK 'SelAuto [PgPrimName, EnumColumn] a 'Prim)
enum =
column primEnumMods
readShow ::
∀ a .
Dd ('DdK 'SelAuto [PgPrimName, ReadShowColumn] a 'Prim)
readShow =
column primReadShowMods
primNullable ::
∀ a .
Dd ('DdK 'SelAuto '[Nullable] (Maybe a) 'Prim)
primNullable =
nullable (prim @a)
primAs ::
∀ name a .
KnownSymbol name =>
Dd ('DdK ('SelSymbol name) '[] a 'Prim)
primAs =
named @name (prim @a)
-- TODO are composite arrays legal?
array ::
∀ f a p sel .
Dd ('DdK sel p a 'Prim) ->
Dd ('DdK sel (ArrayColumn f : p) (f a) 'Prim)
array (Dd sel (Mods p) s) =
Dd sel (Mods (I ArrayColumn :* p)) s
migrateDef ::
∀ s0 s1 .
MapMod (MigrationDefault (DdType s0)) s0 s1 =>
DdType s0 ->
Dd s0 ->
Dd s1
migrateDef a =
setMod (MigrationDefault a)
migrateRename ::
∀ name s0 s1 .
MapMod (MigrationRename name) s0 s1 =>
Dd s0 ->
Dd s1
migrateRename =
setMod (MigrationRename @name)
migrateRenameType ::
∀ name s0 s1 .
MapMod (MigrationRenameType name) s0 s1 =>
Dd s0 ->
Dd s1
migrateRenameType =
setMod (MigrationRenameType @name)
migrateDelete ::
∀ s0 s1 .
MapMod MigrationDelete s0 s1 =>
Dd s0 ->
Dd s1
migrateDelete =
setMod MigrationDelete
newtype Prims a s =
Prims { unPrims :: NP Dd s }
deriving stock (Generic)
class MkPrims as s | as -> s where
mkPrims :: NP Dd s
instance MkPrims '[] '[] where
mkPrims = Nil
instance (
MkPrims as s
) => MkPrims (a : as) ('DdK 'SelAuto '[] a 'Prim : s) where
mkPrims = prim :* mkPrims @as @s
type family PrimProd (a :: Type) :: [Type] where
PrimProd (ConCol _ _ _ as) = as
PrimProd a = ProductGCode a
prims ::
∀ (a :: Type) (s :: [DdK]) .
MkPrims (PrimProd a) s =>
Prims a s
prims =
Prims (mkPrims @(PrimProd a))
class MkPrimNewtypes as s | as -> s where
mkPrimNewtypes :: NP Dd s
instance MkPrimNewtypes '[] '[] where
mkPrimNewtypes = Nil
instance (
MkPrimNewtypes as s,
err ~ NewtypeError,
UnwrapNewtype err a w
) => MkPrimNewtypes (a : as) ('DdK 'SelAuto '[Newtype a w] a 'Prim : s) where
mkPrimNewtypes = primNewtype :* mkPrimNewtypes @as @s
primNewtypes ::
∀ (a :: Type) (s :: [DdK]) .
MkPrimNewtypes (PrimProd a) s =>
Prims a s
primNewtypes =
Prims (mkPrimNewtypes @(PrimProd a))