module Database.PostgreSQL.Query.TH.Entity
( EntityOptions(..)
, deriveEntity
) where
import Prelude
import Data.Default
import Data.String
import Database.PostgreSQL.Query.Entity ( Entity(..) )
import Database.PostgreSQL.Query.TH.Common
import Database.PostgreSQL.Query.Types ( FN(..) )
import Database.PostgreSQL.Simple.FromField
import Database.PostgreSQL.Simple.ToField
import GHC.Generics (Generic)
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Text.Inflections
data EntityOptions = EntityOptions
{ eoTableName :: String -> String
, eoColumnNames :: String -> String
, eoDeriveClasses :: [Name]
, eoIdType :: Name
} deriving (Generic)
instance Default EntityOptions where
def = EntityOptions
{ eoTableName = toUnderscore
, eoColumnNames = toUnderscore
, eoDeriveClasses = [ ''Ord, ''Eq, ''Show
, ''FromField, ''ToField ]
, eoIdType = ''Integer
}
deriveEntity :: EntityOptions -> Name -> Q [Dec]
deriveEntity opts tname = do
TyConI (DataD _ _ _ [tcon] _) <- reify tname
econt <- [t|Entity $(conT tname)|]
ConT entityIdName <- [t|EntityId|]
let tnames = nameBase tname
idname = tnames ++ "Id"
unidname = "get" ++ idname
idtype = ConT (eoIdType opts)
idcon = RecC (mkName idname)
[(mkName unidname, NotStrict, idtype)]
iddec = NewtypeInstD [] entityIdName [ConT tname]
idcon (eoDeriveClasses opts)
tblName = fromString $ eoTableName opts tnames
fldNames = map (fromString . eoColumnNames opts . nameBase)
$ cFieldNames tcon
VarE ntableName <- [e|tableName|]
VarE nfieldNames <- [e|fieldNames|]
tblExp <- lift (tblName :: FN)
fldExp <- mapM lift (fldNames :: [FN])
let tbldec = FunD ntableName [Clause [WildP] (NormalB tblExp) []]
flddec = FunD nfieldNames [Clause [WildP] (NormalB $ ListE fldExp) []]
ret = InstanceD [] econt
[ iddec, tbldec, flddec ]
syndec = TySynD (mkName idname) [] (AppT (ConT entityIdName) (ConT tname))
return [ret, syndec]