TH.hs 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822
  1. {-# LANGUAGE CPP #-}
  2. {-# LANGUAGE FlexibleInstances #-}
  3. {-# LANGUAGE OverloadedStrings #-}
  4. {-# LANGUAGE RankNTypes #-}
  5. {-# LANGUAGE RecordWildCards #-}
  6. {-# LANGUAGE TemplateHaskell #-}
  7. {-# LANGUAGE TupleSections #-}
  8. {-# LANGUAGE UndecidableInstances #-}
  9. {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-missing-fields #-}
  10. -- | This module provides utilities for creating backends. Regular users do not
  11. -- need to use this module.
  12. module Database.Persist.TH
  13. ( -- * Parse entity defs
  14. persistWith
  15. , persistUpperCase
  16. , persistLowerCase
  17. , persistFileWith
  18. , persistManyFileWith
  19. -- * Turn @EntityDef@s into types
  20. , mkPersist
  21. , MkPersistSettings
  22. , mpsBackend
  23. , mpsGeneric
  24. , mpsPrefixFields
  25. , mpsEntityJSON
  26. , mpsGenerateLenses
  27. , EntityJSON(..)
  28. , mkPersistSettings
  29. , sqlSettings
  30. -- * Various other TH functions
  31. , mkMigrate
  32. , mkSave
  33. , mkDeleteCascade
  34. , mkEntityDefList
  35. , share
  36. , derivePersistField
  37. , derivePersistFieldJSON
  38. , persistFieldFromEntity
  39. -- * Internal
  40. , lensPTH
  41. , parseReferences
  42. , AtLeastOneUniqueKey(..)
  43. , OnlyOneUniqueKey(..)
  44. ) where
  45. import Prelude hiding ((++), take, concat, splitAt, exp)
  46. import Control.Monad (forM, unless, (<=<), mzero)
  47. import Data.Aeson
  48. ( ToJSON (toJSON), FromJSON (parseJSON), (.=), object
  49. , Value (Object), (.:), (.:?)
  50. , eitherDecodeStrict'
  51. )
  52. import Data.Char (toLower, toUpper)
  53. import qualified Data.HashMap.Strict as HM
  54. import Data.Int (Int64)
  55. import Data.List (foldl')
  56. import qualified Data.List.NonEmpty as NEL
  57. import qualified Data.Map as M
  58. import Data.Maybe (isJust, listToMaybe, mapMaybe, fromMaybe)
  59. import Data.Monoid (mappend, mconcat)
  60. import Data.Proxy (Proxy (Proxy))
  61. import Data.Text (pack, Text, append, unpack, concat, uncons, cons, stripPrefix, stripSuffix)
  62. import qualified Data.Text as T
  63. import Data.Text.Encoding (decodeUtf8)
  64. import qualified Data.Text.Encoding as TE
  65. import qualified Data.Text.IO as TIO
  66. import GHC.Generics (Generic)
  67. import GHC.TypeLits
  68. import Language.Haskell.TH.Lib (conT, varE)
  69. import Language.Haskell.TH.Quote
  70. import Language.Haskell.TH.Syntax
  71. import qualified System.IO as SIO
  72. import Text.Read (readPrec, lexP, step, prec, parens, Lexeme(Ident))
  73. import Web.PathPieces (PathPiece(..))
  74. import Web.HttpApiData (ToHttpApiData(..), FromHttpApiData(..))
  75. import Database.Persist
  76. import Database.Persist.Sql (Migration, PersistFieldSql, SqlBackend, migrate, sqlType)
  77. import Database.Persist.Quasi
  78. -- | This special-cases "type_" and strips out its underscore. When
  79. -- used for JSON serialization and deserialization, it works around
  80. -- <https://github.com/yesodweb/persistent/issues/412>
  81. unHaskellNameForJSON :: HaskellName -> Text
  82. unHaskellNameForJSON = fixTypeUnderscore . unHaskellName
  83. where fixTypeUnderscore "type" = "type_"
  84. fixTypeUnderscore name = name
  85. -- | Converts a quasi-quoted syntax into a list of entity definitions, to be
  86. -- used as input to the template haskell generation code (mkPersist).
  87. persistWith :: PersistSettings -> QuasiQuoter
  88. persistWith ps = QuasiQuoter
  89. { quoteExp = parseReferences ps . pack
  90. }
  91. -- | Apply 'persistWith' to 'upperCaseSettings'.
  92. persistUpperCase :: QuasiQuoter
  93. persistUpperCase = persistWith upperCaseSettings
  94. -- | Apply 'persistWith' to 'lowerCaseSettings'.
  95. persistLowerCase :: QuasiQuoter
  96. persistLowerCase = persistWith lowerCaseSettings
  97. -- | Same as 'persistWith', but uses an external file instead of a
  98. -- quasiquotation. The recommended file extension is @.persistentmodels@.
  99. persistFileWith :: PersistSettings -> FilePath -> Q Exp
  100. persistFileWith ps fp = persistManyFileWith ps [fp]
  101. -- | Same as 'persistFileWith', but uses several external files instead of
  102. -- one. Splitting your Persistent definitions into multiple modules can
  103. -- potentially dramatically speed up compile times.
  104. --
  105. -- The recommended file extension is @.persistentmodels@.
  106. --
  107. -- ==== __Examples__
  108. --
  109. -- Split your Persistent definitions into multiple files (@models1@, @models2@),
  110. -- then create a new module for each new file and run 'mkPersist' there:
  111. --
  112. -- @
  113. -- -- Model1.hs
  114. -- 'share'
  115. -- ['mkPersist' 'sqlSettings']
  116. -- $('persistFileWith' 'lowerCaseSettings' "models1")
  117. -- @
  118. -- @
  119. -- -- Model2.hs
  120. -- 'share'
  121. -- ['mkPersist' 'sqlSettings']
  122. -- $('persistFileWith' 'lowerCaseSettings' "models2")
  123. -- @
  124. --
  125. -- Use 'persistManyFileWith' to create your migrations:
  126. --
  127. -- @
  128. -- -- Migrate.hs
  129. -- 'share'
  130. -- ['mkMigrate' "migrateAll"]
  131. -- $('persistManyFileWith' 'lowerCaseSettings' ["models1.persistentmodels","models2.persistentmodels"])
  132. -- @
  133. --
  134. -- Tip: To get the same import behavior as if you were declaring all your models in
  135. -- one file, import your new files @as Name@ into another file, then export @module Name@.
  136. --
  137. -- This approach may be used in the future to reduce memory usage during compilation,
  138. -- but so far we've only seen mild reductions.
  139. --
  140. -- See <https://github.com/yesodweb/persistent/issues/778 persistent#778> and
  141. -- <https://github.com/yesodweb/persistent/pull/791 persistent#791> for more details.
  142. --
  143. -- @since 2.5.4
  144. persistManyFileWith :: PersistSettings -> [FilePath] -> Q Exp
  145. persistManyFileWith ps fps = do
  146. mapM_ qAddDependentFile fps
  147. ss <- mapM getS fps
  148. let s = T.intercalate "\n" ss -- be tolerant of the user forgetting to put a line-break at EOF.
  149. parseReferences ps s
  150. where
  151. getS fp = do
  152. h <- qRunIO $ SIO.openFile fp SIO.ReadMode
  153. qRunIO $ SIO.hSetEncoding h SIO.utf8_bom
  154. s <- qRunIO $ TIO.hGetContents h
  155. return s
  156. -- calls parse to Quasi.parse individual entities in isolation
  157. -- afterwards, sets references to other entities
  158. -- | @since 2.5.3
  159. parseReferences :: PersistSettings -> Text -> Q Exp
  160. parseReferences ps s = lift $
  161. map (mkEntityDefSqlTypeExp embedEntityMap entMap) noCycleEnts
  162. where
  163. entMap = M.fromList $ map (\ent -> (entityHaskell ent, ent)) noCycleEnts
  164. noCycleEnts = map breakCycleEnt entsWithEmbeds
  165. -- every EntityDef could reference each-other (as an EmbedRef)
  166. -- let Haskell tie the knot
  167. embedEntityMap = M.fromList $ map (\ent -> (entityHaskell ent, toEmbedEntityDef ent)) entsWithEmbeds
  168. entsWithEmbeds = map setEmbedEntity rawEnts
  169. setEmbedEntity ent = ent
  170. { entityFields = map (setEmbedField (entityHaskell ent) embedEntityMap) $ entityFields ent
  171. }
  172. rawEnts = parse ps s
  173. -- self references are already broken
  174. -- look at every emFieldEmbed to see if it refers to an already seen HaskellName
  175. -- so start with entityHaskell ent and accumulate embeddedHaskell em
  176. breakCycleEnt entDef =
  177. let entName = entityHaskell entDef
  178. in entDef { entityFields = map (breakCycleField entName) $ entityFields entDef }
  179. breakCycleField entName f@(FieldDef { fieldReference = EmbedRef em }) =
  180. f { fieldReference = EmbedRef $ breakCycleEmbed [entName] em }
  181. breakCycleField _ f = f
  182. breakCycleEmbed ancestors em =
  183. em { embeddedFields = map (breakCycleEmField $ emName : ancestors)
  184. (embeddedFields em)
  185. }
  186. where
  187. emName = embeddedHaskell em
  188. breakCycleEmField ancestors emf = case embeddedHaskell <$> membed of
  189. Nothing -> emf
  190. Just embName -> if embName `elem` ancestors
  191. then emf { emFieldEmbed = Nothing, emFieldCycle = Just embName }
  192. else emf { emFieldEmbed = breakCycleEmbed ancestors <$> membed }
  193. where
  194. membed = emFieldEmbed emf
  195. stripId :: FieldType -> Maybe Text
  196. stripId (FTTypeCon Nothing t) = stripSuffix "Id" t
  197. stripId _ = Nothing
  198. foreignReference :: FieldDef -> Maybe HaskellName
  199. foreignReference field = case fieldReference field of
  200. ForeignRef ref _ -> Just ref
  201. _ -> Nothing
  202. -- fieldSqlType at parse time can be an Exp
  203. -- This helps delay setting fieldSqlType until lift time
  204. data EntityDefSqlTypeExp = EntityDefSqlTypeExp EntityDef SqlTypeExp [SqlTypeExp]
  205. deriving Show
  206. data SqlTypeExp = SqlTypeExp FieldType
  207. | SqlType' SqlType
  208. deriving Show
  209. instance Lift SqlTypeExp where
  210. lift (SqlType' t) = lift t
  211. lift (SqlTypeExp ftype) = return st
  212. where
  213. typ = ftToType ftype
  214. mtyp = (ConT ''Proxy `AppT` typ)
  215. typedNothing = SigE (ConE 'Proxy) mtyp
  216. st = VarE 'sqlType `AppE` typedNothing
  217. data FieldsSqlTypeExp = FieldsSqlTypeExp [FieldDef] [SqlTypeExp]
  218. instance Lift FieldsSqlTypeExp where
  219. lift (FieldsSqlTypeExp fields sqlTypeExps) =
  220. lift $ zipWith FieldSqlTypeExp fields sqlTypeExps
  221. data FieldSqlTypeExp = FieldSqlTypeExp FieldDef SqlTypeExp
  222. instance Lift FieldSqlTypeExp where
  223. lift (FieldSqlTypeExp (FieldDef{..}) sqlTypeExp) =
  224. [|FieldDef fieldHaskell fieldDB fieldType $(lift sqlTypeExp) fieldAttrs fieldStrict fieldReference fieldComments|]
  225. instance Lift EntityDefSqlTypeExp where
  226. lift (EntityDefSqlTypeExp ent sqlTypeExp sqlTypeExps) =
  227. [|ent { entityFields = $(lift $ FieldsSqlTypeExp (entityFields ent) sqlTypeExps)
  228. , entityId = $(lift $ FieldSqlTypeExp (entityId ent) sqlTypeExp)
  229. }
  230. |]
  231. instance Lift ReferenceDef where
  232. lift NoReference = [|NoReference|]
  233. lift (ForeignRef name ft) = [|ForeignRef name ft|]
  234. lift (EmbedRef em) = [|EmbedRef em|]
  235. lift (CompositeRef cdef) = [|CompositeRef cdef|]
  236. lift (SelfReference) = [|SelfReference|]
  237. instance Lift EmbedEntityDef where
  238. lift (EmbedEntityDef name fields) = [|EmbedEntityDef name fields|]
  239. instance Lift EmbedFieldDef where
  240. lift (EmbedFieldDef name em cyc) = [|EmbedFieldDef name em cyc|]
  241. type EmbedEntityMap = M.Map HaskellName EmbedEntityDef
  242. type EntityMap = M.Map HaskellName EntityDef
  243. data FTTypeConDescr = FTKeyCon deriving Show
  244. mEmbedded :: EmbedEntityMap -> FieldType -> Either (Maybe FTTypeConDescr) EmbedEntityDef
  245. mEmbedded _ (FTTypeCon Just{} _) = Left Nothing
  246. mEmbedded ents (FTTypeCon Nothing n) = let name = HaskellName n in
  247. maybe (Left Nothing) Right $ M.lookup name ents
  248. mEmbedded ents (FTList x) = mEmbedded ents x
  249. mEmbedded ents (FTApp x y) =
  250. -- Key converts an Record to a RecordId
  251. -- special casing this is obviously a hack
  252. -- This problem may not be solvable with the current QuasiQuoted approach though
  253. if x == FTTypeCon Nothing "Key"
  254. then Left $ Just FTKeyCon
  255. else mEmbedded ents y
  256. setEmbedField :: HaskellName -> EmbedEntityMap -> FieldDef -> FieldDef
  257. setEmbedField entName allEntities field = field
  258. { fieldReference = case fieldReference field of
  259. NoReference ->
  260. case mEmbedded allEntities (fieldType field) of
  261. Left _ -> case stripId $ fieldType field of
  262. Nothing -> NoReference
  263. Just name -> case M.lookup (HaskellName name) allEntities of
  264. Nothing -> NoReference
  265. Just _ -> ForeignRef (HaskellName name)
  266. -- This can get corrected in mkEntityDefSqlTypeExp
  267. (FTTypeCon (Just "Data.Int") "Int64")
  268. Right em -> if embeddedHaskell em /= entName
  269. then EmbedRef em
  270. else if maybeNullable field
  271. then SelfReference
  272. else case fieldType field of
  273. FTList _ -> SelfReference
  274. _ -> error $ unpack $ unHaskellName entName
  275. `Data.Monoid.mappend` ": a self reference must be a Maybe"
  276. existing@_ -> existing
  277. }
  278. mkEntityDefSqlTypeExp :: EmbedEntityMap -> EntityMap -> EntityDef -> EntityDefSqlTypeExp
  279. mkEntityDefSqlTypeExp emEntities entMap ent = EntityDefSqlTypeExp ent
  280. (getSqlType $ entityId ent)
  281. $ (map getSqlType $ entityFields ent)
  282. where
  283. getSqlType field = maybe
  284. (defaultSqlTypeExp field)
  285. (SqlType' . SqlOther)
  286. (listToMaybe $ mapMaybe (stripPrefix "sqltype=") $ fieldAttrs field)
  287. -- In the case of embedding, there won't be any datatype created yet.
  288. -- We just use SqlString, as the data will be serialized to JSON.
  289. defaultSqlTypeExp field = case mEmbedded emEntities ftype of
  290. Right _ -> SqlType' SqlString
  291. Left (Just FTKeyCon) -> SqlType' SqlString
  292. Left Nothing -> case fieldReference field of
  293. ForeignRef refName ft -> case M.lookup refName entMap of
  294. Nothing -> SqlTypeExp ft
  295. -- A ForeignRef is blindly set to an Int64 in setEmbedField
  296. -- correct that now
  297. Just ent' -> case entityPrimary ent' of
  298. Nothing -> SqlTypeExp ft
  299. Just pdef -> case compositeFields pdef of
  300. [] -> error "mkEntityDefSqlTypeExp: no composite fields"
  301. [x] -> SqlTypeExp $ fieldType x
  302. _ -> SqlType' $ SqlOther "Composite Reference"
  303. CompositeRef _ -> SqlType' $ SqlOther "Composite Reference"
  304. _ -> case ftype of
  305. -- In the case of lists, we always serialize to a string
  306. -- value (via JSON).
  307. --
  308. -- Normally, this would be determined automatically by
  309. -- SqlTypeExp. However, there's one corner case: if there's
  310. -- a list of entity IDs, the datatype for the ID has not
  311. -- yet been created, so the compiler will fail. This extra
  312. -- clause works around this limitation.
  313. FTList _ -> SqlType' SqlString
  314. _ -> SqlTypeExp ftype
  315. where
  316. ftype = fieldType field
  317. -- | Create data types and appropriate 'PersistEntity' instances for the given
  318. -- 'EntityDef's. Works well with the persist quasi-quoter.
  319. mkPersist :: MkPersistSettings -> [EntityDef] -> Q [Dec]
  320. mkPersist mps ents' = do
  321. x <- fmap Data.Monoid.mconcat $ mapM (persistFieldFromEntity mps) ents
  322. y <- fmap mconcat $ mapM (mkEntity entMap mps) ents
  323. z <- fmap mconcat $ mapM (mkJSON mps) ents
  324. uniqueKeyInstances <- fmap mconcat $ mapM (mkUniqueKeyInstances mps) ents
  325. return $ mconcat [x, y, z, uniqueKeyInstances]
  326. where
  327. ents = map fixEntityDef ents'
  328. entMap = M.fromList $ map (\ent -> (entityHaskell ent, ent)) ents
  329. -- | Implement special preprocessing on EntityDef as necessary for 'mkPersist'.
  330. -- For example, strip out any fields marked as MigrationOnly.
  331. fixEntityDef :: EntityDef -> EntityDef
  332. fixEntityDef ed =
  333. ed { entityFields = filter keepField $ entityFields ed }
  334. where
  335. keepField fd = "MigrationOnly" `notElem` fieldAttrs fd &&
  336. "SafeToRemove" `notElem` fieldAttrs fd
  337. -- | Settings to be passed to the 'mkPersist' function.
  338. data MkPersistSettings = MkPersistSettings
  339. { mpsBackend :: Type
  340. -- ^ Which database backend we\'re using.
  341. --
  342. -- When generating data types, each type is given a generic version- which
  343. -- works with any backend- and a type synonym for the commonly used
  344. -- backend. This is where you specify that commonly used backend.
  345. , mpsGeneric :: Bool
  346. -- ^ Create generic types that can be used with multiple backends. Good for
  347. -- reusable code, but makes error messages harder to understand. Default:
  348. -- False.
  349. , mpsPrefixFields :: Bool
  350. -- ^ Prefix field names with the model name. Default: True.
  351. , mpsEntityJSON :: Maybe EntityJSON
  352. -- ^ Generate @ToJSON@/@FromJSON@ instances for each model types. If it's
  353. -- @Nothing@, no instances will be generated. Default:
  354. --
  355. -- @
  356. -- Just EntityJSON
  357. -- { entityToJSON = 'keyValueEntityToJSON
  358. -- , entityFromJSON = 'keyValueEntityFromJSON
  359. -- }
  360. -- @
  361. , mpsGenerateLenses :: !Bool
  362. -- ^ Instead of generating normal field accessors, generator lens-style accessors.
  363. --
  364. -- Default: False
  365. --
  366. -- @since 1.3.1
  367. }
  368. data EntityJSON = EntityJSON
  369. { entityToJSON :: Name
  370. -- ^ Name of the @toJSON@ implementation for @Entity a@.
  371. , entityFromJSON :: Name
  372. -- ^ Name of the @fromJSON@ implementation for @Entity a@.
  373. }
  374. -- | Create an @MkPersistSettings@ with default values.
  375. mkPersistSettings :: Type -- ^ Value for 'mpsBackend'
  376. -> MkPersistSettings
  377. mkPersistSettings t = MkPersistSettings
  378. { mpsBackend = t
  379. , mpsGeneric = False
  380. , mpsPrefixFields = True
  381. , mpsEntityJSON = Just EntityJSON
  382. { entityToJSON = 'entityIdToJSON
  383. , entityFromJSON = 'entityIdFromJSON
  384. }
  385. , mpsGenerateLenses = False
  386. }
  387. -- | Use the 'SqlPersist' backend.
  388. sqlSettings :: MkPersistSettings
  389. sqlSettings = mkPersistSettings $ ConT ''SqlBackend
  390. recNameNoUnderscore :: MkPersistSettings -> HaskellName -> HaskellName -> Text
  391. recNameNoUnderscore mps dt f
  392. | mpsPrefixFields mps = lowerFirst (unHaskellName dt) ++ upperFirst ft
  393. | otherwise = lowerFirst ft
  394. where ft = unHaskellName f
  395. recName :: MkPersistSettings -> HaskellName -> HaskellName -> Text
  396. recName mps dt f =
  397. addUnderscore $ recNameNoUnderscore mps dt f
  398. where
  399. addUnderscore
  400. | mpsGenerateLenses mps = ("_" ++)
  401. | otherwise = id
  402. lowerFirst :: Text -> Text
  403. lowerFirst t =
  404. case uncons t of
  405. Just (a, b) -> cons (toLower a) b
  406. Nothing -> t
  407. upperFirst :: Text -> Text
  408. upperFirst t =
  409. case uncons t of
  410. Just (a, b) -> cons (toUpper a) b
  411. Nothing -> t
  412. dataTypeDec :: MkPersistSettings -> EntityDef -> Q Dec
  413. dataTypeDec mps t = do
  414. let names = map (mkName . unpack) $ entityDerives t
  415. #if MIN_VERSION_template_haskell(2,12,0)
  416. DataD [] nameFinal paramsFinal
  417. Nothing
  418. constrs
  419. <$> fmap (pure . DerivClause Nothing) (mapM conT names)
  420. #else
  421. DataD [] nameFinal paramsFinal
  422. Nothing
  423. constrs
  424. <$> mapM conT names
  425. #endif
  426. where
  427. mkCol x fd@FieldDef {..} =
  428. (mkName $ unpack $ recName mps x fieldHaskell,
  429. if fieldStrict then isStrict else notStrict,
  430. maybeIdType mps fd Nothing Nothing
  431. )
  432. (nameFinal, paramsFinal)
  433. | mpsGeneric mps = (nameG, [PlainTV backend])
  434. | otherwise = (name, [])
  435. nameG = mkName $ unpack $ unHaskellName (entityHaskell t) ++ "Generic"
  436. name = mkName $ unpack $ unHaskellName $ entityHaskell t
  437. cols = map (mkCol $ entityHaskell t) $ entityFields t
  438. backend = backendName
  439. constrs
  440. | entitySum t = map sumCon $ entityFields t
  441. | otherwise = [RecC name cols]
  442. sumCon fd = NormalC
  443. (sumConstrName mps t fd)
  444. [(notStrict, maybeIdType mps fd Nothing Nothing)]
  445. sumConstrName :: MkPersistSettings -> EntityDef -> FieldDef -> Name
  446. sumConstrName mps t FieldDef {..} = mkName $ unpack $ concat
  447. [ if mpsPrefixFields mps
  448. then unHaskellName $ entityHaskell t
  449. else ""
  450. , upperFirst $ unHaskellName fieldHaskell
  451. , "Sum"
  452. ]
  453. uniqueTypeDec :: MkPersistSettings -> EntityDef -> Dec
  454. uniqueTypeDec mps t =
  455. DataInstD [] ''Unique
  456. [genericDataType mps (entityHaskell t) backendT]
  457. Nothing
  458. (map (mkUnique mps t) $ entityUniques t)
  459. (derivClause $ entityUniques t)
  460. where
  461. derivClause [] = []
  462. #if MIN_VERSION_template_haskell(2,12,0)
  463. derivClause _ = [DerivClause Nothing [ConT ''Show]]
  464. #else
  465. derivClause _ = [ConT ''Show]
  466. #endif
  467. mkUnique :: MkPersistSettings -> EntityDef -> UniqueDef -> Con
  468. mkUnique mps t (UniqueDef (HaskellName constr) _ fields attrs) =
  469. NormalC (mkName $ unpack constr) types
  470. where
  471. types = map (go . flip lookup3 (entityFields t))
  472. $ map (unHaskellName . fst) fields
  473. force = "!force" `elem` attrs
  474. go :: (FieldDef, IsNullable) -> (Strict, Type)
  475. go (_, Nullable _) | not force = error nullErrMsg
  476. go (fd, y) = (notStrict, maybeIdType mps fd Nothing (Just y))
  477. lookup3 :: Text -> [FieldDef] -> (FieldDef, IsNullable)
  478. lookup3 s [] =
  479. error $ unpack $ "Column not found: " ++ s ++ " in unique " ++ constr
  480. lookup3 x (fd@FieldDef {..}:rest)
  481. | x == unHaskellName fieldHaskell = (fd, nullable fieldAttrs)
  482. | otherwise = lookup3 x rest
  483. nullErrMsg =
  484. mconcat [ "Error: By default we disallow NULLables in an uniqueness "
  485. , "constraint. The semantics of how NULL interacts with those "
  486. , "constraints is non-trivial: two NULL values are not "
  487. , "considered equal for the purposes of an uniqueness "
  488. , "constraint. If you understand this feature, it is possible "
  489. , "to use it your advantage. *** Use a \"!force\" attribute "
  490. , "on the end of the line that defines your uniqueness "
  491. , "constraint in order to disable this check. ***" ]
  492. maybeIdType :: MkPersistSettings
  493. -> FieldDef
  494. -> Maybe Name -- ^ backend
  495. -> Maybe IsNullable
  496. -> Type
  497. maybeIdType mps fd mbackend mnull = maybeTyp mayNullable idtyp
  498. where
  499. mayNullable = case mnull of
  500. (Just (Nullable ByMaybeAttr)) -> True
  501. _ -> maybeNullable fd
  502. idtyp = idType mps fd mbackend
  503. backendDataType :: MkPersistSettings -> Type
  504. backendDataType mps
  505. | mpsGeneric mps = backendT
  506. | otherwise = mpsBackend mps
  507. genericDataType :: MkPersistSettings
  508. -> HaskellName -- ^ entity name
  509. -> Type -- ^ backend
  510. -> Type
  511. genericDataType mps (HaskellName typ') backend
  512. | mpsGeneric mps = ConT (mkName $ unpack $ typ' ++ "Generic") `AppT` backend
  513. | otherwise = ConT $ mkName $ unpack typ'
  514. idType :: MkPersistSettings -> FieldDef -> Maybe Name -> Type
  515. idType mps fd mbackend =
  516. case foreignReference fd of
  517. Just typ ->
  518. ConT ''Key
  519. `AppT` genericDataType mps typ (VarT $ fromMaybe backendName mbackend)
  520. Nothing -> ftToType $ fieldType fd
  521. degen :: [Clause] -> [Clause]
  522. degen [] =
  523. let err = VarE 'error `AppE` LitE (StringL
  524. "Degenerate case, should never happen")
  525. in [normalClause [WildP] err]
  526. degen x = x
  527. mkToPersistFields :: MkPersistSettings -> String -> EntityDef -> Q Dec
  528. mkToPersistFields mps constr ed@EntityDef { entitySum = isSum, entityFields = fields } = do
  529. clauses <-
  530. if isSum
  531. then sequence $ zipWith goSum fields [1..]
  532. else fmap return go
  533. return $ FunD 'toPersistFields clauses
  534. where
  535. go :: Q Clause
  536. go = do
  537. xs <- sequence $ replicate fieldCount $ newName "x"
  538. let pat = ConP (mkName constr) $ map VarP xs
  539. sp <- [|SomePersistField|]
  540. let bod = ListE $ map (AppE sp . VarE) xs
  541. return $ normalClause [pat] bod
  542. fieldCount = length fields
  543. goSum :: FieldDef -> Int -> Q Clause
  544. goSum fd idx = do
  545. let name = sumConstrName mps ed fd
  546. enull <- [|SomePersistField PersistNull|]
  547. let beforeCount = idx - 1
  548. afterCount = fieldCount - idx
  549. before = replicate beforeCount enull
  550. after = replicate afterCount enull
  551. x <- newName "x"
  552. sp <- [|SomePersistField|]
  553. let body = ListE $ mconcat
  554. [ before
  555. , [sp `AppE` VarE x]
  556. , after
  557. ]
  558. return $ normalClause [ConP name [VarP x]] body
  559. mkToFieldNames :: [UniqueDef] -> Q Dec
  560. mkToFieldNames pairs = do
  561. pairs' <- mapM go pairs
  562. return $ FunD 'persistUniqueToFieldNames $ degen pairs'
  563. where
  564. go (UniqueDef constr _ names _) = do
  565. names' <- lift names
  566. return $
  567. normalClause
  568. [RecP (mkName $ unpack $ unHaskellName constr) []]
  569. names'
  570. mkUniqueToValues :: [UniqueDef] -> Q Dec
  571. mkUniqueToValues pairs = do
  572. pairs' <- mapM go pairs
  573. return $ FunD 'persistUniqueToValues $ degen pairs'
  574. where
  575. go :: UniqueDef -> Q Clause
  576. go (UniqueDef constr _ names _) = do
  577. xs <- mapM (const $ newName "x") names
  578. let pat = ConP (mkName $ unpack $ unHaskellName constr) $ map VarP xs
  579. tpv <- [|toPersistValue|]
  580. let bod = ListE $ map (AppE tpv . VarE) xs
  581. return $ normalClause [pat] bod
  582. isNotNull :: PersistValue -> Bool
  583. isNotNull PersistNull = False
  584. isNotNull _ = True
  585. mapLeft :: (a -> c) -> Either a b -> Either c b
  586. mapLeft _ (Right r) = Right r
  587. mapLeft f (Left l) = Left (f l)
  588. mkFromPersistValues :: MkPersistSettings -> EntityDef -> Q [Clause]
  589. mkFromPersistValues _ t@(EntityDef { entitySum = False }) =
  590. fromValues t "fromPersistValues" entE $ entityFields t
  591. where
  592. entE = ConE $ mkName $ unpack entName
  593. entName = unHaskellName $ entityHaskell t
  594. mkFromPersistValues mps t@(EntityDef { entitySum = True }) = do
  595. nothing <- [|Left ("Invalid fromPersistValues input: sum type with all nulls. Entity: " `mappend` entName)|]
  596. clauses <- mkClauses [] $ entityFields t
  597. return $ clauses `mappend` [normalClause [WildP] nothing]
  598. where
  599. entName = unHaskellName $ entityHaskell t
  600. mkClauses _ [] = return []
  601. mkClauses before (field:after) = do
  602. x <- newName "x"
  603. let null' = ConP 'PersistNull []
  604. pat = ListP $ mconcat
  605. [ map (const null') before
  606. , [VarP x]
  607. , map (const null') after
  608. ]
  609. constr = ConE $ sumConstrName mps t field
  610. fs <- [|fromPersistValue $(return $ VarE x)|]
  611. let guard' = NormalG $ VarE 'isNotNull `AppE` VarE x
  612. let clause = Clause [pat] (GuardedB [(guard', InfixE (Just constr) fmapE (Just fs))]) []
  613. clauses <- mkClauses (field : before) after
  614. return $ clause : clauses
  615. type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
  616. lensPTH :: (s -> a) -> (s -> b -> t) -> Lens s t a b
  617. lensPTH sa sbt afb s = fmap (sbt s) (afb $ sa s)
  618. fmapE :: Exp
  619. fmapE = VarE 'fmap
  620. mkLensClauses :: MkPersistSettings -> EntityDef -> Q [Clause]
  621. mkLensClauses mps t = do
  622. lens' <- [|lensPTH|]
  623. getId <- [|entityKey|]
  624. setId <- [|\(Entity _ value) key -> Entity key value|]
  625. getVal <- [|entityVal|]
  626. dot <- [|(.)|]
  627. keyVar <- newName "key"
  628. valName <- newName "value"
  629. xName <- newName "x"
  630. let idClause = normalClause
  631. [ConP (keyIdName t) []]
  632. (lens' `AppE` getId `AppE` setId)
  633. if entitySum t
  634. then return $ idClause : map (toSumClause lens' keyVar valName xName) (entityFields t)
  635. else return $ idClause : map (toClause lens' getVal dot keyVar valName xName) (entityFields t)
  636. where
  637. toClause lens' getVal dot keyVar valName xName f = normalClause
  638. [ConP (filterConName mps t f) []]
  639. (lens' `AppE` getter `AppE` setter)
  640. where
  641. fieldName = mkName $ unpack $ recName mps (entityHaskell t) (fieldHaskell f)
  642. getter = InfixE (Just $ VarE fieldName) dot (Just getVal)
  643. setter = LamE
  644. [ ConP 'Entity [VarP keyVar, VarP valName]
  645. , VarP xName
  646. ]
  647. $ ConE 'Entity `AppE` VarE keyVar `AppE` RecUpdE
  648. (VarE valName)
  649. [(fieldName, VarE xName)]
  650. toSumClause lens' keyVar valName xName f = normalClause
  651. [ConP (filterConName mps t f) []]
  652. (lens' `AppE` getter `AppE` setter)
  653. where
  654. emptyMatch = Match WildP (NormalB $ VarE 'error `AppE` LitE (StringL "Tried to use fieldLens on a Sum type")) []
  655. getter = LamE
  656. [ ConP 'Entity [WildP, VarP valName]
  657. ] $ CaseE (VarE valName)
  658. $ Match (ConP (sumConstrName mps t f) [VarP xName]) (NormalB $ VarE xName) []
  659. -- FIXME It would be nice if the types expressed that the Field is
  660. -- a sum type and therefore could result in Maybe.
  661. : if length (entityFields t) > 1 then [emptyMatch] else []
  662. setter = LamE
  663. [ ConP 'Entity [VarP keyVar, WildP]
  664. , VarP xName
  665. ]
  666. $ ConE 'Entity `AppE` VarE keyVar `AppE` (ConE (sumConstrName mps t f) `AppE` VarE xName)
  667. -- | declare the key type and associated instances
  668. -- @'PathPiece'@, @'ToHttpApiData'@ and @'FromHttpApiData'@ instances are only generated for a Key with one field
  669. mkKeyTypeDec :: MkPersistSettings -> EntityDef -> Q (Dec, [Dec])
  670. mkKeyTypeDec mps t = do
  671. (instDecs, i) <-
  672. if mpsGeneric mps
  673. then if not useNewtype
  674. then do pfDec <- pfInstD
  675. return (pfDec, [''Generic])
  676. else do gi <- genericNewtypeInstances
  677. return (gi, [])
  678. else if not useNewtype
  679. then do pfDec <- pfInstD
  680. return (pfDec, [''Show, ''Read, ''Eq, ''Ord, ''Generic])
  681. else do
  682. let allInstances = [''Show, ''Read, ''Eq, ''Ord, ''PathPiece, ''ToHttpApiData, ''FromHttpApiData, ''PersistField, ''PersistFieldSql, ''ToJSON, ''FromJSON]
  683. if customKeyType
  684. then return ([], allInstances)
  685. else do
  686. bi <- backendKeyI
  687. return (bi, allInstances)
  688. #if MIN_VERSION_template_haskell(2,12,0)
  689. cxti <- mapM conT i
  690. let kd = if useNewtype
  691. then NewtypeInstD [] k [recordType] Nothing dec [DerivClause Nothing cxti]
  692. else DataInstD [] k [recordType] Nothing [dec] [DerivClause Nothing cxti]
  693. #else
  694. cxti <- mapM conT i
  695. let kd = if useNewtype
  696. then NewtypeInstD [] k [recordType] Nothing dec cxti
  697. else DataInstD [] k [recordType] Nothing [dec] cxti
  698. #endif
  699. return (kd, instDecs)
  700. where
  701. keyConE = keyConExp t
  702. unKeyE = unKeyExp t
  703. dec = RecC (keyConName t) (keyFields mps t)
  704. k = ''Key
  705. recordType = genericDataType mps (entityHaskell t) backendT
  706. pfInstD = -- FIXME: generate a PersistMap instead of PersistList
  707. [d|instance PersistField (Key $(pure recordType)) where
  708. toPersistValue = PersistList . keyToValues
  709. fromPersistValue (PersistList l) = keyFromValues l
  710. fromPersistValue got = error $ "fromPersistValue: expected PersistList, got: " `mappend` show got
  711. instance PersistFieldSql (Key $(pure recordType)) where
  712. sqlType _ = SqlString
  713. instance ToJSON (Key $(pure recordType))
  714. instance FromJSON (Key $(pure recordType))
  715. |]
  716. keyStringL = StringL . keyString
  717. -- ghc 7.6 cannot parse the left arrow Ident $() <- lexP
  718. keyPattern = BindS (ConP 'Ident [LitP $ keyStringL t])
  719. backendKeyGenericI =
  720. [d| instance PersistStore $(pure backendT) =>
  721. ToBackendKey $(pure backendT) $(pure recordType) where
  722. toBackendKey = $(return unKeyE)
  723. fromBackendKey = $(return keyConE)
  724. |]
  725. backendKeyI = let bdt = backendDataType mps in
  726. [d| instance ToBackendKey $(pure bdt) $(pure recordType) where
  727. toBackendKey = $(return unKeyE)
  728. fromBackendKey = $(return keyConE)
  729. |]
  730. -- truly unfortunate that TH doesn't support standalone deriving
  731. -- https://ghc.haskell.org/trac/ghc/ticket/8100
  732. genericNewtypeInstances = do
  733. instances <- [|lexP|] >>= \lexPE -> [| step readPrec >>= return . ($(pure keyConE) )|] >>= \readE -> do
  734. alwaysInstances <-
  735. [d|instance Show (BackendKey $(pure backendT)) => Show (Key $(pure recordType)) where
  736. showsPrec i x = showParen (i > app_prec) $
  737. (showString $ $(pure $ LitE $ keyStringL t) `mappend` " ") .
  738. showsPrec i ($(return unKeyE) x)
  739. where app_prec = (10::Int)
  740. instance Read (BackendKey $(pure backendT)) => Read (Key $(pure recordType)) where
  741. readPrec = parens $ (prec app_prec $ $(pure $ DoE [keyPattern lexPE, NoBindS readE]))
  742. where app_prec = (10::Int)
  743. instance Eq (BackendKey $(pure backendT)) => Eq (Key $(pure recordType)) where
  744. x == y =
  745. ($(return unKeyE) x) ==
  746. ($(return unKeyE) y)
  747. instance Ord (BackendKey $(pure backendT)) => Ord (Key $(pure recordType)) where
  748. compare x y = compare
  749. ($(return unKeyE) x)
  750. ($(return unKeyE) y)
  751. instance ToHttpApiData (BackendKey $(pure backendT)) => ToHttpApiData (Key $(pure recordType)) where
  752. toUrlPiece = toUrlPiece . $(return unKeyE)
  753. instance FromHttpApiData (BackendKey $(pure backendT)) => FromHttpApiData(Key $(pure recordType)) where
  754. parseUrlPiece = fmap $(return keyConE) . parseUrlPiece
  755. instance PathPiece (BackendKey $(pure backendT)) => PathPiece (Key $(pure recordType)) where
  756. toPathPiece = toPathPiece . $(return unKeyE)
  757. fromPathPiece = fmap $(return keyConE) . fromPathPiece
  758. instance PersistField (BackendKey $(pure backendT)) => PersistField (Key $(pure recordType)) where
  759. toPersistValue = toPersistValue . $(return unKeyE)
  760. fromPersistValue = fmap $(return keyConE) . fromPersistValue
  761. instance PersistFieldSql (BackendKey $(pure backendT)) => PersistFieldSql (Key $(pure recordType)) where
  762. sqlType = sqlType . fmap $(return unKeyE)
  763. instance ToJSON (BackendKey $(pure backendT)) => ToJSON (Key $(pure recordType)) where
  764. toJSON = toJSON . $(return unKeyE)
  765. instance FromJSON (BackendKey $(pure backendT)) => FromJSON (Key $(pure recordType)) where
  766. parseJSON = fmap $(return keyConE) . parseJSON
  767. |]
  768. if customKeyType then return alwaysInstances
  769. else fmap (alwaysInstances `mappend`) backendKeyGenericI
  770. return instances
  771. useNewtype = pkNewtype mps t
  772. customKeyType = not (defaultIdType t) || not useNewtype || isJust (entityPrimary t)
  773. keyIdName :: EntityDef -> Name
  774. keyIdName = mkName . unpack . keyIdText
  775. keyIdText :: EntityDef -> Text
  776. keyIdText t = (unHaskellName $ entityHaskell t) `mappend` "Id"
  777. unKeyName :: EntityDef -> Name
  778. unKeyName t = mkName $ "un" `mappend` keyString t
  779. unKeyExp :: EntityDef -> Exp
  780. unKeyExp = VarE . unKeyName
  781. backendT :: Type
  782. backendT = VarT backendName
  783. backendName :: Name
  784. backendName = mkName "backend"
  785. keyConName :: EntityDef -> Name
  786. keyConName t = mkName $ resolveConflict $ keyString t
  787. where
  788. resolveConflict kn = if conflict then kn `mappend` "'" else kn
  789. conflict = any ((== HaskellName "key") . fieldHaskell) $ entityFields t
  790. keyConExp :: EntityDef -> Exp
  791. keyConExp = ConE . keyConName
  792. keyString :: EntityDef -> String
  793. keyString = unpack . keyText
  794. keyText :: EntityDef -> Text
  795. keyText t = unHaskellName (entityHaskell t) ++ "Key"
  796. pkNewtype :: MkPersistSettings -> EntityDef -> Bool
  797. pkNewtype mps t = length (keyFields mps t) < 2
  798. defaultIdType :: EntityDef -> Bool
  799. defaultIdType t = fieldType (entityId t) == FTTypeCon Nothing (keyIdText t)
  800. keyFields :: MkPersistSettings -> EntityDef -> [(Name, Strict, Type)]
  801. keyFields mps t = case entityPrimary t of
  802. Just pdef -> map primaryKeyVar $ (compositeFields pdef)
  803. Nothing -> if defaultIdType t
  804. then [idKeyVar backendKeyType]
  805. else [idKeyVar $ ftToType $ fieldType $ entityId t]
  806. where
  807. backendKeyType
  808. | mpsGeneric mps = ConT ''BackendKey `AppT` backendT
  809. | otherwise = ConT ''BackendKey `AppT` mpsBackend mps
  810. idKeyVar ft = (unKeyName t, notStrict, ft)
  811. primaryKeyVar fd = ( keyFieldName mps t fd
  812. , notStrict
  813. , ftToType $ fieldType fd
  814. )
  815. keyFieldName :: MkPersistSettings -> EntityDef -> FieldDef -> Name
  816. keyFieldName mps t fd
  817. | pkNewtype mps t = unKeyName t
  818. | otherwise = mkName $ unpack
  819. $ lowerFirst (keyText t) `mappend` (unHaskellName $ fieldHaskell fd)
  820. mkKeyToValues :: MkPersistSettings -> EntityDef -> Q Dec
  821. mkKeyToValues mps t = do
  822. (p, e) <- case entityPrimary t of
  823. Nothing ->
  824. ([],) <$> [|(:[]) . toPersistValue . $(return $ unKeyExp t)|]
  825. Just pdef ->
  826. return $ toValuesPrimary pdef
  827. return $ FunD 'keyToValues $ return $ normalClause p e
  828. where
  829. toValuesPrimary pdef =
  830. ( [VarP recordName]
  831. , ListE $ map (\fd -> VarE 'toPersistValue `AppE` (VarE (keyFieldName mps t fd) `AppE` VarE recordName)) $ compositeFields pdef
  832. )
  833. recordName = mkName "record"
  834. normalClause :: [Pat] -> Exp -> Clause
  835. normalClause p e = Clause p (NormalB e) []
  836. mkKeyFromValues :: MkPersistSettings -> EntityDef -> Q Dec
  837. mkKeyFromValues _mps t = do
  838. clauses <- case entityPrimary t of
  839. Nothing -> do
  840. e <- [|fmap $(return $ keyConE) . fromPersistValue . headNote|]
  841. return $ [normalClause [] e]
  842. Just pdef ->
  843. fromValues t "keyFromValues" keyConE (compositeFields pdef)
  844. return $ FunD 'keyFromValues clauses
  845. where
  846. keyConE = keyConExp t
  847. headNote :: [PersistValue] -> PersistValue
  848. headNote (x:[]) = x
  849. headNote xs = error $ "mkKeyFromValues: expected a list of one element, got: "
  850. `mappend` show xs
  851. fromValues :: EntityDef -> Text -> Exp -> [FieldDef] -> Q [Clause]
  852. fromValues t funName conE fields = do
  853. x <- newName "x"
  854. let funMsg = entityText t `mappend` ": " `mappend` funName `mappend` " failed on: "
  855. patternMatchFailure <- [|Left $ mappend funMsg (pack $ show $(return $ VarE x))|]
  856. suc <- patternSuccess
  857. return [ suc, normalClause [VarP x] patternMatchFailure ]
  858. where
  859. patternSuccess =
  860. case fields of
  861. [] -> do
  862. rightE <- [|Right|]
  863. return $ normalClause [ListP []] (rightE `AppE` conE)
  864. _ -> do
  865. x1 <- newName "x1"
  866. restNames <- mapM (\i -> newName $ "x" `mappend` show i) [2..length fields]
  867. (fpv1:mkPersistValues) <- mapM mkPersistValue fields
  868. app1E <- [|(<$>)|]
  869. let conApp = infixFromPersistValue app1E fpv1 conE x1
  870. applyE <- [|(<*>)|]
  871. let applyFromPersistValue = infixFromPersistValue applyE
  872. return $ normalClause
  873. [ListP $ map VarP (x1:restNames)]
  874. (foldl' (\exp (name, fpv) -> applyFromPersistValue fpv exp name) conApp (zip restNames mkPersistValues))
  875. infixFromPersistValue applyE fpv exp name =
  876. UInfixE exp applyE (fpv `AppE` VarE name)
  877. mkPersistValue field =
  878. [|mapLeft (fieldError t field) . fromPersistValue|]
  879. fieldError :: EntityDef -> FieldDef -> Text -> Text
  880. fieldError entity field err = mconcat
  881. [ "Couldn't parse field `"
  882. , fieldName
  883. , "` from table `"
  884. , tableName
  885. , "`. "
  886. , err
  887. ]
  888. where
  889. fieldName =
  890. unHaskellName (fieldHaskell field)
  891. tableName =
  892. unDBName (entityDB entity)
  893. mkEntity :: EntityMap -> MkPersistSettings -> EntityDef -> Q [Dec]
  894. mkEntity entMap mps t = do
  895. t' <- liftAndFixKeys entMap t
  896. let nameT = unHaskellName entName
  897. let nameS = unpack nameT
  898. let clazz = ConT ''PersistEntity `AppT` genDataType
  899. tpf <- mkToPersistFields mps nameS t
  900. fpv <- mkFromPersistValues mps t
  901. utv <- mkUniqueToValues $ entityUniques t
  902. puk <- mkUniqueKeys t
  903. fkc <- mapM (mkForeignKeysComposite mps t) $ entityForeigns t
  904. let primaryField = entityId t
  905. fields <- mapM (mkField mps t) $ primaryField : entityFields t
  906. toFieldNames <- mkToFieldNames $ entityUniques t
  907. (keyTypeDec, keyInstanceDecs) <- mkKeyTypeDec mps t
  908. keyToValues' <- mkKeyToValues mps t
  909. keyFromValues' <- mkKeyFromValues mps t
  910. let addSyn -- FIXME maybe remove this
  911. | mpsGeneric mps = (:) $
  912. TySynD (mkName nameS) [] $
  913. genericDataType mps entName $ mpsBackend mps
  914. | otherwise = id
  915. lensClauses <- mkLensClauses mps t
  916. lenses <- mkLenses mps t
  917. let instanceConstraint = if not (mpsGeneric mps) then [] else
  918. [mkClassP ''PersistStore [backendT]]
  919. dtd <- dataTypeDec mps t
  920. return $ addSyn $
  921. dtd : mconcat fkc `mappend`
  922. ([ TySynD (keyIdName t) [] $
  923. ConT ''Key `AppT` ConT (mkName nameS)
  924. , instanceD instanceConstraint clazz $
  925. [ uniqueTypeDec mps t
  926. , keyTypeDec
  927. , keyToValues'
  928. , keyFromValues'
  929. , FunD 'entityDef [normalClause [WildP] t']
  930. , tpf
  931. , FunD 'fromPersistValues fpv
  932. , toFieldNames
  933. , utv
  934. , puk
  935. , DataInstD
  936. []
  937. ''EntityField
  938. [ genDataType
  939. , VarT $ mkName "typ"
  940. ]
  941. Nothing
  942. (map fst fields)
  943. []
  944. , FunD 'persistFieldDef (map snd fields)
  945. , TySynInstD
  946. ''PersistEntityBackend
  947. (TySynEqn
  948. [genDataType]
  949. (backendDataType mps))
  950. , FunD 'persistIdField [normalClause [] (ConE $ keyIdName t)]
  951. , FunD 'fieldLens lensClauses
  952. ]
  953. ] `mappend` lenses) `mappend` keyInstanceDecs
  954. where
  955. genDataType = genericDataType mps entName backendT
  956. entName = entityHaskell t
  957. mkUniqueKeyInstances :: MkPersistSettings -> EntityDef -> Q [Dec]
  958. mkUniqueKeyInstances mps t = do
  959. -- FIXME: isExtEnabled breaks the benchmark
  960. undecidableInstancesEnabled <- isExtEnabled UndecidableInstances
  961. unless undecidableInstancesEnabled . fail
  962. $ "Generating Persistent entities now requires the 'UndecidableInstances' "
  963. `mappend` "language extension. Please enable it in your file by copy/pasting "
  964. `mappend` "this line into the top of your file: \n\n"
  965. `mappend` "{-# LANGUAGE UndecidableInstances #-}"
  966. case entityUniques t of
  967. [] -> mappend <$> typeErrorSingle <*> typeErrorAtLeastOne
  968. [_] -> mappend <$> singleUniqueKey <*> atLeastOneKey
  969. (_:_) -> mappend <$> typeErrorMultiple <*> atLeastOneKey
  970. where
  971. requireUniquesPName = mkName "requireUniquesP"
  972. onlyUniquePName = mkName "onlyUniqueP"
  973. typeErrorSingle = mkOnlyUniqueError typeErrorNoneCtx
  974. typeErrorMultiple = mkOnlyUniqueError typeErrorMultipleCtx
  975. withPersistStoreWriteCxt =
  976. if mpsGeneric mps
  977. then do
  978. write <- [t|PersistStoreWrite $(pure (VarT $ mkName "backend")) |]
  979. pure [write]
  980. else do
  981. pure []
  982. typeErrorNoneCtx = do
  983. tyErr <- [t|TypeError (NoUniqueKeysError $(pure genDataType))|]
  984. (tyErr :) <$> withPersistStoreWriteCxt
  985. typeErrorMultipleCtx = do
  986. tyErr <- [t|TypeError (MultipleUniqueKeysError $(pure genDataType))|]
  987. (tyErr :) <$> withPersistStoreWriteCxt
  988. mkOnlyUniqueError :: Q Cxt -> Q [Dec]
  989. mkOnlyUniqueError mkCtx = do
  990. ctx <- mkCtx
  991. let impl = mkImpossible onlyUniquePName
  992. pure [instanceD ctx onlyOneUniqueKeyClass impl]
  993. mkImpossible name =
  994. [ FunD name
  995. [ Clause
  996. [ WildP ]
  997. (NormalB
  998. (VarE (mkName "error") `AppE` LitE (StringL "impossible"))
  999. )
  1000. []
  1001. ]
  1002. ]
  1003. typeErrorAtLeastOne :: Q [Dec]
  1004. typeErrorAtLeastOne = do
  1005. let impl = mkImpossible requireUniquesPName
  1006. cxt <- typeErrorMultipleCtx
  1007. pure [instanceD cxt atLeastOneUniqueKeyClass impl]
  1008. singleUniqueKey :: Q [Dec]
  1009. singleUniqueKey = do
  1010. expr <- [e|\p -> head (persistUniqueKeys p)|]
  1011. let impl = [FunD onlyUniquePName [Clause [] (NormalB expr) []]]
  1012. cxt <- withPersistStoreWriteCxt
  1013. pure [instanceD cxt onlyOneUniqueKeyClass impl]
  1014. atLeastOneUniqueKeyClass = ConT ''AtLeastOneUniqueKey `AppT` genDataType
  1015. onlyOneUniqueKeyClass = ConT ''OnlyOneUniqueKey `AppT` genDataType
  1016. atLeastOneKey :: Q [Dec]
  1017. atLeastOneKey = do
  1018. expr <- [e|\p -> NEL.fromList (persistUniqueKeys p)|]
  1019. let impl = [FunD requireUniquesPName [Clause [] (NormalB expr) []]]
  1020. cxt <- withPersistStoreWriteCxt
  1021. pure [instanceD cxt atLeastOneUniqueKeyClass impl]
  1022. genDataType = genericDataType mps (entityHaskell t) backendT
  1023. entityText :: EntityDef -> Text
  1024. entityText = unHaskellName . entityHaskell
  1025. mkLenses :: MkPersistSettings -> EntityDef -> Q [Dec]
  1026. mkLenses mps _ | not (mpsGenerateLenses mps) = return []
  1027. mkLenses _ ent | entitySum ent = return []
  1028. mkLenses mps ent = fmap mconcat $ forM (entityFields ent) $ \field -> do
  1029. let lensName' = recNameNoUnderscore mps (entityHaskell ent) (fieldHaskell field)
  1030. lensName = mkName $ unpack lensName'
  1031. fieldName = mkName $ unpack $ "_" ++ lensName'
  1032. needleN <- newName "needle"
  1033. setterN <- newName "setter"
  1034. fN <- newName "f"
  1035. aN <- newName "a"
  1036. yN <- newName "y"
  1037. let needle = VarE needleN
  1038. setter = VarE setterN
  1039. f = VarE fN
  1040. a = VarE aN
  1041. y = VarE yN
  1042. fT = mkName "f"
  1043. -- FIXME if we want to get really fancy, then: if this field is the
  1044. -- *only* Id field present, then set backend1 and backend2 to different
  1045. -- values
  1046. backend1 = backendName
  1047. backend2 = backendName
  1048. aT = maybeIdType mps field (Just backend1) Nothing
  1049. bT = maybeIdType mps field (Just backend2) Nothing
  1050. mkST backend = genericDataType mps (entityHaskell ent) (VarT backend)
  1051. sT = mkST backend1
  1052. tT = mkST backend2
  1053. t1 `arrow` t2 = ArrowT `AppT` t1 `AppT` t2
  1054. vars = PlainTV fT
  1055. : (if mpsGeneric mps then [PlainTV backend1{-, PlainTV backend2-}] else [])
  1056. return
  1057. [ SigD lensName $ ForallT vars [mkClassP ''Functor [VarT fT]] $
  1058. (aT `arrow` (VarT fT `AppT` bT)) `arrow`
  1059. (sT `arrow` (VarT fT `AppT` tT))
  1060. , FunD lensName $ return $ Clause
  1061. [VarP fN, VarP aN]
  1062. (NormalB $ fmapE
  1063. `AppE` setter
  1064. `AppE` (f `AppE` needle))
  1065. [ FunD needleN [normalClause [] (VarE fieldName `AppE` a)]
  1066. , FunD setterN $ return $ normalClause
  1067. [VarP yN]
  1068. (RecUpdE a
  1069. [ (fieldName, y)
  1070. ])
  1071. ]
  1072. ]
  1073. mkForeignKeysComposite :: MkPersistSettings -> EntityDef -> ForeignDef -> Q [Dec]
  1074. mkForeignKeysComposite mps t ForeignDef {..} = do
  1075. let fieldName f = mkName $ unpack $ recName mps (entityHaskell t) f
  1076. let fname = fieldName foreignConstraintNameHaskell
  1077. let reftableString = unpack $ unHaskellName $ foreignRefTableHaskell
  1078. let reftableKeyName = mkName $ reftableString `mappend` "Key"
  1079. let tablename = mkName $ unpack $ entityText t
  1080. recordName <- newName "record"
  1081. let fldsE = map (\((foreignName, _),_) -> VarE (fieldName $ foreignName)
  1082. `AppE` VarE recordName) foreignFields
  1083. let mkKeyE = foldl' AppE (maybeExp foreignNullable $ ConE reftableKeyName) fldsE
  1084. let fn = FunD fname [normalClause [VarP recordName] mkKeyE]
  1085. let t2 = maybeTyp foreignNullable $ ConT ''Key `AppT` ConT (mkName reftableString)
  1086. let sig = SigD fname $ (ArrowT `AppT` (ConT tablename)) `AppT` t2
  1087. return [sig, fn]
  1088. maybeExp :: Bool -> Exp -> Exp
  1089. maybeExp may exp | may = fmapE `AppE` exp
  1090. | otherwise = exp
  1091. maybeTyp :: Bool -> Type -> Type
  1092. maybeTyp may typ | may = ConT ''Maybe `AppT` typ
  1093. | otherwise = typ
  1094. -- | produce code similar to the following:
  1095. --
  1096. -- @
  1097. -- instance PersistEntity e => PersistField e where
  1098. -- toPersistValue = PersistMap $ zip columNames (map toPersistValue . toPersistFields)
  1099. -- fromPersistValue (PersistMap o) =
  1100. -- let columns = HM.fromList o
  1101. -- in fromPersistValues $ map (\name ->
  1102. -- case HM.lookup name columns of
  1103. -- Just v -> v
  1104. -- Nothing -> PersistNull
  1105. -- fromPersistValue x = Left $ "Expected PersistMap, received: " ++ show x
  1106. -- sqlType _ = SqlString
  1107. -- @
  1108. persistFieldFromEntity :: MkPersistSettings -> EntityDef -> Q [Dec]
  1109. persistFieldFromEntity mps e = do
  1110. ss <- [|SqlString|]
  1111. obj <- [|\ent -> PersistMap $ zip (map pack columnNames) (map toPersistValue $ toPersistFields ent)|]
  1112. fpv <- [|\x -> let columns = HM.fromList x
  1113. in fromPersistValues $ map
  1114. (\(name) ->
  1115. case HM.lookup (pack name) columns of
  1116. Just v -> v
  1117. Nothing -> PersistNull)
  1118. $ columnNames
  1119. |]
  1120. compose <- [|(<=<)|]
  1121. getPersistMap' <- [|getPersistMap|]
  1122. return
  1123. [ persistFieldInstanceD (mpsGeneric mps) typ
  1124. [ FunD 'toPersistValue [ normalClause [] obj ]
  1125. , FunD 'fromPersistValue
  1126. [ normalClause [] (InfixE (Just fpv) compose $ Just getPersistMap')
  1127. ]
  1128. ]
  1129. , persistFieldSqlInstanceD (mpsGeneric mps) typ
  1130. [ sqlTypeFunD ss
  1131. ]
  1132. ]
  1133. where
  1134. typ = genericDataType mps (entityHaskell e) backendT
  1135. entFields = entityFields e
  1136. columnNames = map (unpack . unHaskellName . fieldHaskell) entFields
  1137. -- | Apply the given list of functions to the same @EntityDef@s.
  1138. --
  1139. -- This function is useful for cases such as:
  1140. --
  1141. -- >>> share [mkSave "myDefs", mkPersist sqlSettings] [persistLowerCase|...|]
  1142. share :: [[EntityDef] -> Q [Dec]] -> [EntityDef] -> Q [Dec]
  1143. share fs x = fmap mconcat $ mapM ($ x) fs
  1144. -- | Save the @EntityDef@s passed in under the given name.
  1145. mkSave :: String -> [EntityDef] -> Q [Dec]
  1146. mkSave name' defs' = do
  1147. let name = mkName name'
  1148. defs <- lift defs'
  1149. return [ SigD name $ ListT `AppT` ConT ''EntityDef
  1150. , FunD name [normalClause [] defs]
  1151. ]
  1152. data Dep = Dep
  1153. { depTarget :: HaskellName
  1154. , depSourceTable :: HaskellName
  1155. , depSourceField :: HaskellName
  1156. , depSourceNull :: IsNullable
  1157. }
  1158. -- | Generate a 'DeleteCascade' instance for the given @EntityDef@s.
  1159. mkDeleteCascade :: MkPersistSettings -> [EntityDef] -> Q [Dec]
  1160. mkDeleteCascade mps defs = do
  1161. let deps = concatMap getDeps defs
  1162. mapM (go deps) defs
  1163. where
  1164. getDeps :: EntityDef -> [Dep]
  1165. getDeps def =
  1166. concatMap getDeps' $ entityFields $ fixEntityDef def
  1167. where
  1168. getDeps' :: FieldDef -> [Dep]
  1169. getDeps' field@FieldDef {..} =
  1170. case foreignReference field of
  1171. Just name ->
  1172. return Dep
  1173. { depTarget = name
  1174. , depSourceTable = entityHaskell def
  1175. , depSourceField = fieldHaskell
  1176. , depSourceNull = nullable fieldAttrs
  1177. }
  1178. Nothing -> []
  1179. go :: [Dep] -> EntityDef -> Q Dec
  1180. go allDeps EntityDef{entityHaskell = name} = do
  1181. let deps = filter (\x -> depTarget x == name) allDeps
  1182. key <- newName "key"
  1183. let del = VarE 'delete
  1184. let dcw = VarE 'deleteCascadeWhere
  1185. just <- [|Just|]
  1186. filt <- [|Filter|]
  1187. eq <- [|Eq|]
  1188. value <- [|FilterValue|]
  1189. let mkStmt :: Dep -> Stmt
  1190. mkStmt dep = NoBindS
  1191. $ dcw `AppE`
  1192. ListE
  1193. [ filt `AppE` ConE filtName
  1194. `AppE` (value `AppE` val (depSourceNull dep))
  1195. `AppE` eq
  1196. ]
  1197. where
  1198. filtName = filterConName' mps (depSourceTable dep) (depSourceField dep)
  1199. val (Nullable ByMaybeAttr) = just `AppE` VarE key
  1200. val _ = VarE key
  1201. let stmts :: [Stmt]
  1202. stmts = map mkStmt deps `mappend`
  1203. [NoBindS $ del `AppE` VarE key]
  1204. let entityT = genericDataType mps name backendT
  1205. return $
  1206. instanceD
  1207. [ mkClassP ''PersistQuery [backendT]
  1208. , mkEqualP (ConT ''PersistEntityBackend `AppT` entityT) (ConT ''BaseBackend `AppT` backendT)
  1209. ]
  1210. (ConT ''DeleteCascade `AppT` entityT `AppT` backendT)
  1211. [ FunD 'deleteCascade
  1212. [normalClause [VarP key] (DoE stmts)]
  1213. ]
  1214. -- | Creates a declaration for the @['EntityDef']@ from the @persistent@
  1215. -- schema. This is necessary because the Persistent QuasiQuoter is unable
  1216. -- to know the correct type of ID fields, and assumes that they are all
  1217. -- Int64.
  1218. --
  1219. -- Provide this in the list you give to 'share', much like @'mkMigrate'@.
  1220. --
  1221. -- @
  1222. -- 'share' ['mkMigrate' "migrateAll", 'mkEntityDefList' "entityDefs"] [...]
  1223. -- @
  1224. --
  1225. -- @since 2.7.1
  1226. mkEntityDefList
  1227. :: String
  1228. -- ^ The name that will be given to the 'EntityDef' list.
  1229. -> [EntityDef]
  1230. -> Q [Dec]
  1231. mkEntityDefList entityList entityDefs = do
  1232. let entityListName = mkName entityList
  1233. edefs <- fmap ListE
  1234. . forM entityDefs
  1235. $ \(EntityDef { entityHaskell = HaskellName haskellName }) ->
  1236. let entityType = conT (mkName (T.unpack haskellName))
  1237. in [|entityDef (Proxy :: Proxy $(entityType))|]
  1238. typ <- [t|[EntityDef]|]
  1239. pure
  1240. [ SigD entityListName typ
  1241. , ValD (VarP entityListName) (NormalB edefs) []
  1242. ]
  1243. mkUniqueKeys :: EntityDef -> Q Dec
  1244. mkUniqueKeys def | entitySum def =
  1245. return $ FunD 'persistUniqueKeys [normalClause [WildP] (ListE [])]
  1246. mkUniqueKeys def = do
  1247. c <- clause
  1248. return $ FunD 'persistUniqueKeys [c]
  1249. where
  1250. clause = do
  1251. xs <- forM (entityFields def) $ \fd -> do
  1252. let x = fieldHaskell fd
  1253. x' <- newName $ '_' : unpack (unHaskellName x)
  1254. return (x, x')
  1255. let pcs = map (go xs) $ entityUniques def
  1256. let pat = ConP
  1257. (mkName $ unpack $ unHaskellName $ entityHaskell def)
  1258. (map (VarP . snd) xs)
  1259. return $ normalClause [pat] (ListE pcs)
  1260. go :: [(HaskellName, Name)] -> UniqueDef -> Exp
  1261. go xs (UniqueDef name _ cols _) =
  1262. foldl' (go' xs) (ConE (mkName $ unpack $ unHaskellName name)) (map fst cols)
  1263. go' :: [(HaskellName, Name)] -> Exp -> HaskellName -> Exp
  1264. go' xs front col =
  1265. let Just col' = lookup col xs
  1266. in front `AppE` VarE col'
  1267. sqlTypeFunD :: Exp -> Dec
  1268. sqlTypeFunD st = FunD 'sqlType
  1269. [ normalClause [WildP] st ]
  1270. typeInstanceD :: Name
  1271. -> Bool -- ^ include PersistStore backend constraint
  1272. -> Type -> [Dec] -> Dec
  1273. typeInstanceD clazz hasBackend typ =
  1274. instanceD ctx (ConT clazz `AppT` typ)
  1275. where
  1276. ctx
  1277. | hasBackend = [mkClassP ''PersistStore [backendT]]
  1278. | otherwise = []
  1279. persistFieldInstanceD :: Bool -- ^ include PersistStore backend constraint
  1280. -> Type -> [Dec] -> Dec
  1281. persistFieldInstanceD = typeInstanceD ''PersistField
  1282. persistFieldSqlInstanceD :: Bool -- ^ include PersistStore backend constraint
  1283. -> Type -> [Dec] -> Dec
  1284. persistFieldSqlInstanceD = typeInstanceD ''PersistFieldSql
  1285. -- | Automatically creates a valid 'PersistField' instance for any datatype
  1286. -- that has valid 'Show' and 'Read' instances. Can be very convenient for
  1287. -- 'Enum' types.
  1288. derivePersistField :: String -> Q [Dec]
  1289. derivePersistField s = do
  1290. ss <- [|SqlString|]
  1291. tpv <- [|PersistText . pack . show|]
  1292. fpv <- [|\dt v ->
  1293. case fromPersistValue v of
  1294. Left e -> Left e
  1295. Right s' ->
  1296. case reads $ unpack s' of
  1297. (x, _):_ -> Right x
  1298. [] -> Left $ pack "Invalid " ++ pack dt ++ pack ": " ++ s'|]
  1299. return
  1300. [ persistFieldInstanceD False (ConT $ mkName s)
  1301. [ FunD 'toPersistValue
  1302. [ normalClause [] tpv
  1303. ]
  1304. , FunD 'fromPersistValue
  1305. [ normalClause [] (fpv `AppE` LitE (StringL s))
  1306. ]
  1307. ]
  1308. , persistFieldSqlInstanceD False (ConT $ mkName s)
  1309. [ sqlTypeFunD ss
  1310. ]
  1311. ]
  1312. -- | Automatically creates a valid 'PersistField' instance for any datatype
  1313. -- that has valid 'ToJSON' and 'FromJSON' instances. For a datatype @T@ it
  1314. -- generates instances similar to these:
  1315. --
  1316. -- @
  1317. -- instance PersistField T where
  1318. -- toPersistValue = PersistByteString . L.toStrict . encode
  1319. -- fromPersistValue = (left T.pack) . eitherDecodeStrict' <=< fromPersistValue
  1320. -- instance PersistFieldSql T where
  1321. -- sqlType _ = SqlString
  1322. -- @
  1323. derivePersistFieldJSON :: String -> Q [Dec]
  1324. derivePersistFieldJSON s = do
  1325. ss <- [|SqlString|]
  1326. tpv <- [|PersistText . toJsonText|]
  1327. fpv <- [|\dt v -> do
  1328. text <- fromPersistValue v
  1329. let bs' = TE.encodeUtf8 text
  1330. case eitherDecodeStrict' bs' of
  1331. Left e -> Left $ pack "JSON decoding error for " ++ pack dt ++ pack ": " ++ pack e ++ pack ". On Input: " ++ decodeUtf8 bs'
  1332. Right x -> Right x|]
  1333. return
  1334. [ persistFieldInstanceD False (ConT $ mkName s)
  1335. [ FunD 'toPersistValue
  1336. [ normalClause [] tpv
  1337. ]
  1338. , FunD 'fromPersistValue
  1339. [ normalClause [] (fpv `AppE` LitE (StringL s))
  1340. ]
  1341. ]
  1342. , persistFieldSqlInstanceD False (ConT $ mkName s)
  1343. [ sqlTypeFunD ss
  1344. ]
  1345. ]
  1346. -- | Creates a single function to perform all migrations for the entities
  1347. -- defined here. One thing to be aware of is dependencies: if you have entities
  1348. -- with foreign references, make sure to place those definitions after the
  1349. -- entities they reference.
  1350. mkMigrate :: String -> [EntityDef] -> Q [Dec]
  1351. mkMigrate fun allDefs = do
  1352. body' <- body
  1353. return
  1354. [ SigD (mkName fun) typ
  1355. , FunD (mkName fun) [normalClause [] body']
  1356. ]
  1357. where
  1358. defs = filter isMigrated allDefs
  1359. isMigrated def = not $ "no-migrate" `elem` entityAttrs def
  1360. typ = ConT ''Migration
  1361. entMap = M.fromList $ map (\ent -> (entityHaskell ent, ent)) allDefs
  1362. body :: Q Exp
  1363. body =
  1364. case defs of
  1365. [] -> [|return ()|]
  1366. _ -> do
  1367. defsName <- newName "defs"
  1368. defsStmt <- do
  1369. defs' <- mapM (liftAndFixKeys entMap) defs
  1370. let defsExp = ListE defs'
  1371. return $ LetS [ValD (VarP defsName) (NormalB defsExp) []]
  1372. stmts <- mapM (toStmt $ VarE defsName) defs
  1373. return (DoE $ defsStmt : stmts)
  1374. toStmt :: Exp -> EntityDef -> Q Stmt
  1375. toStmt defsExp ed = do
  1376. u <- liftAndFixKeys entMap ed
  1377. m <- [|migrate|]
  1378. return $ NoBindS $ m `AppE` defsExp `AppE` u
  1379. liftAndFixKeys :: EntityMap -> EntityDef -> Q Exp
  1380. liftAndFixKeys entMap EntityDef{..} =
  1381. [|EntityDef
  1382. entityHaskell
  1383. entityDB
  1384. entityId
  1385. entityAttrs
  1386. $(ListE <$> mapM (liftAndFixKey entMap) entityFields)
  1387. entityUniques
  1388. entityForeigns
  1389. entityDerives
  1390. entityExtra
  1391. entitySum
  1392. entityComments
  1393. |]
  1394. liftAndFixKey :: EntityMap -> FieldDef -> Q Exp
  1395. liftAndFixKey entMap (FieldDef a b c sqlTyp e f fieldRef mcomments) =
  1396. [|FieldDef a b c $(sqlTyp') e f fieldRef' mcomments|]
  1397. where
  1398. (fieldRef', sqlTyp') = fromMaybe (fieldRef, lift sqlTyp) $
  1399. case fieldRef of
  1400. ForeignRef refName _ft -> case M.lookup refName entMap of
  1401. Nothing -> Nothing
  1402. Just ent ->
  1403. case fieldReference $ entityId ent of
  1404. fr@(ForeignRef _Name ft) -> Just (fr, lift $ SqlTypeExp ft)
  1405. _ -> Nothing
  1406. _ -> Nothing
  1407. instance Lift EntityDef where
  1408. lift EntityDef{..} =
  1409. [|EntityDef
  1410. entityHaskell
  1411. entityDB
  1412. entityId
  1413. entityAttrs
  1414. entityFields
  1415. entityUniques
  1416. entityForeigns
  1417. entityDerives
  1418. entityExtra
  1419. entitySum
  1420. entityComments
  1421. |]
  1422. instance Lift FieldDef where
  1423. lift (FieldDef a b c d e f g h) = [|FieldDef a b c d e f g h|]
  1424. instance Lift UniqueDef where
  1425. lift (UniqueDef a b c d) = [|UniqueDef a b c d|]
  1426. instance Lift CompositeDef where
  1427. lift (CompositeDef a b) = [|CompositeDef a b|]
  1428. instance Lift ForeignDef where
  1429. lift (ForeignDef a b c d e f g) = [|ForeignDef a b c d e f g|]
  1430. -- | A hack to avoid orphans.
  1431. class Lift' a where
  1432. lift' :: a -> Q Exp
  1433. instance Lift' Text where
  1434. lift' = liftT
  1435. instance Lift' a => Lift' [a] where
  1436. lift' xs = do { xs' <- mapM lift' xs; return (ListE xs') }
  1437. instance (Lift' k, Lift' v) => Lift' (M.Map k v) where
  1438. lift' m = [|M.fromList $(fmap ListE $ mapM liftPair $ M.toList m)|]
  1439. -- overlapping instances is for automatic lifting
  1440. -- while avoiding an orphan of Lift for Text
  1441. -- auto-lifting, means instances are overlapping
  1442. instance {-# OVERLAPPABLE #-} Lift' a => Lift a where
  1443. lift = lift'
  1444. liftT :: Text -> Q Exp
  1445. liftT t = [|pack $(lift (unpack t))|]
  1446. liftPair :: (Lift' k, Lift' v) => (k, v) -> Q Exp
  1447. liftPair (k, v) = [|($(lift' k), $(lift' v))|]
  1448. instance Lift HaskellName where
  1449. lift (HaskellName t) = [|HaskellName t|]
  1450. instance Lift DBName where
  1451. lift (DBName t) = [|DBName t|]
  1452. instance Lift FieldType where
  1453. lift (FTTypeCon Nothing t) = [|FTTypeCon Nothing t|]
  1454. lift (FTTypeCon (Just x) t) = [|FTTypeCon (Just x) t|]
  1455. lift (FTApp x y) = [|FTApp x y|]
  1456. lift (FTList x) = [|FTList x|]
  1457. instance Lift PersistFilter where
  1458. lift Eq = [|Eq|]
  1459. lift Ne = [|Ne|]
  1460. lift Gt = [|Gt|]
  1461. lift Lt = [|Lt|]
  1462. lift Ge = [|Ge|]
  1463. lift Le = [|Le|]
  1464. lift In = [|In|]
  1465. lift NotIn = [|NotIn|]
  1466. lift (BackendSpecificFilter x) = [|BackendSpecificFilter x|]
  1467. instance Lift PersistUpdate where
  1468. lift Assign = [|Assign|]
  1469. lift Add = [|Add|]
  1470. lift Subtract = [|Subtract|]
  1471. lift Multiply = [|Multiply|]
  1472. lift Divide = [|Divide|]
  1473. lift (BackendSpecificUpdate x) = [|BackendSpecificUpdate x|]
  1474. instance Lift SqlType where
  1475. lift SqlString = [|SqlString|]
  1476. lift SqlInt32 = [|SqlInt32|]
  1477. lift SqlInt64 = [|SqlInt64|]
  1478. lift SqlReal = [|SqlReal|]
  1479. lift (SqlNumeric x y) =
  1480. [|SqlNumeric (fromInteger x') (fromInteger y')|]
  1481. where
  1482. x' = fromIntegral x :: Integer
  1483. y' = fromIntegral y :: Integer
  1484. lift SqlBool = [|SqlBool|]
  1485. lift SqlDay = [|SqlDay|]
  1486. lift SqlTime = [|SqlTime|]
  1487. lift SqlDayTime = [|SqlDayTime|]
  1488. lift SqlBlob = [|SqlBlob|]
  1489. lift (SqlOther a) = [|SqlOther a|]
  1490. -- Ent
  1491. -- fieldName FieldType
  1492. --
  1493. -- forall . typ ~ FieldType => EntFieldName
  1494. --
  1495. -- EntFieldName = FieldDef ....
  1496. mkField :: MkPersistSettings -> EntityDef -> FieldDef -> Q (Con, Clause)
  1497. mkField mps et cd = do
  1498. let con = ForallC
  1499. []
  1500. [mkEqualP (VarT $ mkName "typ") $ maybeIdType mps cd Nothing Nothing]
  1501. $ NormalC name []
  1502. bod <- lift cd
  1503. let cla = normalClause
  1504. [ConP name []]
  1505. bod
  1506. return (con, cla)
  1507. where
  1508. name = filterConName mps et cd
  1509. maybeNullable :: FieldDef -> Bool
  1510. maybeNullable fd = nullable (fieldAttrs fd) == Nullable ByMaybeAttr
  1511. filterConName :: MkPersistSettings
  1512. -> EntityDef
  1513. -> FieldDef
  1514. -> Name
  1515. filterConName mps entity field = filterConName' mps (entityHaskell entity) (fieldHaskell field)
  1516. filterConName' :: MkPersistSettings
  1517. -> HaskellName -- ^ table
  1518. -> HaskellName -- ^ field
  1519. -> Name
  1520. filterConName' mps entity field = mkName $ unpack $ concat
  1521. [ if mpsPrefixFields mps || field == HaskellName "Id"
  1522. then unHaskellName entity
  1523. else ""
  1524. , upperFirst $ unHaskellName field
  1525. ]
  1526. ftToType :: FieldType -> Type
  1527. ftToType (FTTypeCon Nothing t) = ConT $ mkName $ unpack t
  1528. -- This type is generated from the Quasi-Quoter.
  1529. -- Adding this special case avoids users needing to import Data.Int
  1530. ftToType (FTTypeCon (Just "Data.Int") "Int64") = ConT ''Int64
  1531. ftToType (FTTypeCon (Just m) t) = ConT $ mkName $ unpack $ concat [m, ".", t]
  1532. ftToType (FTApp x y) = ftToType x `AppT` ftToType y
  1533. ftToType (FTList x) = ListT `AppT` ftToType x
  1534. infixr 5 ++
  1535. (++) :: Text -> Text -> Text
  1536. (++) = append
  1537. mkJSON :: MkPersistSettings -> EntityDef -> Q [Dec]
  1538. mkJSON _ def | not ("json" `elem` entityAttrs def) = return []
  1539. mkJSON mps def = do
  1540. pureE <- [|pure|]
  1541. apE' <- [|(<*>)|]
  1542. packE <- [|pack|]
  1543. dotEqualE <- [|(.=)|]
  1544. dotColonE <- [|(.:)|]
  1545. dotColonQE <- [|(.:?)|]
  1546. objectE <- [|object|]
  1547. obj <- newName "obj"
  1548. mzeroE <- [|mzero|]
  1549. xs <- mapM (newName . unpack . unHaskellNameForJSON . fieldHaskell)
  1550. $ entityFields def
  1551. let conName = mkName $ unpack $ unHaskellName $ entityHaskell def
  1552. typ = genericDataType mps (entityHaskell def) backendT
  1553. toJSONI = typeInstanceD ''ToJSON (mpsGeneric mps) typ [toJSON']
  1554. toJSON' = FunD 'toJSON $ return $ normalClause
  1555. [ConP conName $ map VarP xs]
  1556. (objectE `AppE` ListE pairs)
  1557. pairs = zipWith toPair (entityFields def) xs
  1558. toPair f x = InfixE
  1559. (Just (packE `AppE` LitE (StringL $ unpack $ unHaskellName $ fieldHaskell f)))
  1560. dotEqualE
  1561. (Just $ VarE x)
  1562. fromJSONI = typeInstanceD ''FromJSON (mpsGeneric mps) typ [parseJSON']
  1563. parseJSON' = FunD 'parseJSON
  1564. [ normalClause [ConP 'Object [VarP obj]]
  1565. (foldl'
  1566. (\x y -> InfixE (Just x) apE' (Just y))
  1567. (pureE `AppE` ConE conName)
  1568. pulls
  1569. )
  1570. , normalClause [WildP] mzeroE
  1571. ]
  1572. pulls = map toPull $ entityFields def
  1573. toPull f = InfixE
  1574. (Just $ VarE obj)
  1575. (if maybeNullable f then dotColonQE else dotColonE)
  1576. (Just $ AppE packE $ LitE $ StringL $ unpack $ unHaskellName $ fieldHaskell f)
  1577. case mpsEntityJSON mps of
  1578. Nothing -> return [toJSONI, fromJSONI]
  1579. Just entityJSON -> do
  1580. entityJSONIs <- if mpsGeneric mps
  1581. then [d|
  1582. instance PersistStore $(pure backendT) => ToJSON (Entity $(pure typ)) where
  1583. toJSON = $(varE (entityToJSON entityJSON))
  1584. instance PersistStore $(pure backendT) => FromJSON (Entity $(pure typ)) where
  1585. parseJSON = $(varE (entityFromJSON entityJSON))
  1586. |]
  1587. else [d|
  1588. instance ToJSON (Entity $(pure typ)) where
  1589. toJSON = $(varE (entityToJSON entityJSON))
  1590. instance FromJSON (Entity $(pure typ)) where
  1591. parseJSON = $(varE (entityFromJSON entityJSON))
  1592. |]
  1593. return $ toJSONI : fromJSONI : entityJSONIs
  1594. mkClassP :: Name -> [Type] -> Pred
  1595. mkClassP cla tys = foldl AppT (ConT cla) tys
  1596. mkEqualP :: Type -> Type -> Pred
  1597. mkEqualP tleft tright = foldl AppT EqualityT [tleft, tright]
  1598. notStrict :: Bang
  1599. notStrict = Bang NoSourceUnpackedness NoSourceStrictness
  1600. isStrict :: Bang
  1601. isStrict = Bang NoSourceUnpackedness SourceStrict
  1602. instanceD :: Cxt -> Type -> [Dec] -> Dec
  1603. instanceD = InstanceD Nothing
  1604. -- entityUpdates :: EntityDef -> [(HaskellName, FieldType, IsNullable, PersistUpdate)]
  1605. -- entityUpdates =
  1606. -- concatMap go . entityFields
  1607. -- where
  1608. -- go FieldDef {..} = map (\a -> (fieldHaskell, fieldType, nullable fieldAttrs, a)) [minBound..maxBound]
  1609. -- mkToUpdate :: String -> [(String, PersistUpdate)] -> Q Dec
  1610. -- mkToUpdate name pairs = do
  1611. -- pairs' <- mapM go pairs
  1612. -- return $ FunD (mkName name) $ degen pairs'
  1613. -- where
  1614. -- go (constr, pu) = do
  1615. -- pu' <- lift pu
  1616. -- return $ normalClause [RecP (mkName constr) []] pu'
  1617. -- mkToFieldName :: String -> [(String, String)] -> Dec
  1618. -- mkToFieldName func pairs =
  1619. -- FunD (mkName func) $ degen $ map go pairs
  1620. -- where
  1621. -- go (constr, name) =
  1622. -- normalClause [RecP (mkName constr) []] (LitE $ StringL name)
  1623. -- mkToValue :: String -> [String] -> Dec
  1624. -- mkToValue func = FunD (mkName func) . degen . map go
  1625. -- where
  1626. -- go constr =
  1627. -- let x = mkName "x"
  1628. -- in normalClause [ConP (mkName constr) [VarP x]]
  1629. -- (VarE 'toPersistValue `AppE` VarE x)