File: Types.hs

package info (click to toggle)
haskell-persistent 2.17.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,196 kB
  • sloc: haskell: 14,076; makefile: 3
file content (142 lines) | stat: -rw-r--r-- 7,974 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
{- You can't export a data family constructor, so there's an "unused" warning -}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

module Database.Persist.Compatible.Types
    ( Compatible(..)
    ) where

import Control.Monad.Trans.Reader (withReaderT)
import Data.Aeson
import Database.Persist.Class
import Database.Persist.Sql.Class


-- | A newtype wrapper for compatible backends, mainly useful for @DerivingVia@.
--
-- When writing a new backend that is 'BackendCompatible' with an existing backend,
-- instances for the new backend can be naturally defined in terms of the
-- instances for the existing backend.
--
-- For example, if you decide to augment the 'SqlBackend' with some additional
-- features:
--
-- @
-- data BetterSqlBackend = BetterSqlBackend { sqlBackend :: SqlBackend, ... }
--
-- instance BackendCompatible SqlBackend BetterSqlBackend where
--   projectBackend = sqlBackend
-- @
--
-- Then you can use @DerivingVia@ to automatically get instances like:
--
-- @
-- deriving via (Compatible SqlBackend BetterSqlBackend) instance PersistStoreRead BetterSqlBackend
-- deriving via (Compatible SqlBackend BetterSqlBackend) instance PersistStoreWrite BetterSqlBackend
-- ...
-- @
--
-- These instances will go through the compatible backend (in this case, 'SqlBackend')
-- for all their queries.
--
-- These instances require that both backends have the same 'BaseBackend', but
-- deriving 'HasPersistBackend' will enforce that for you.
--
-- @
-- deriving via (Compatible SqlBackend BetterSqlBackend) instance HasPersistBackend BetterSqlBackend
-- @
--
-- @since 2.12
newtype Compatible b s = Compatible { unCompatible :: s }

instance (BackendCompatible b s, HasPersistBackend b) => HasPersistBackend (Compatible b s) where
    type BaseBackend (Compatible b s) = BaseBackend b
    persistBackend = persistBackend . projectBackend @b @s . unCompatible

instance (BackendCompatible b s, PersistCore b) => PersistCore (Compatible b s) where
    -- | A newtype wrapper around @'BackendKey' b@, mainly useful for @DerivingVia@.
    --
    -- Similarly to @'Compatible' b s@, this data family instance is handy for deriving
    -- instances for @'BackendKey' s@ by defining them in terms of @'BackendKey' b@.
    --
    --
    -- For example, if you decide to augment the 'SqlBackend' with some additional
    -- features:
    --
    -- @
    -- data BetterSqlBackend = BetterSqlBackend { sqlBackend :: SqlBackend, ... }
    --
    -- instance PersistCore BetterSqlBackend where
    --   newtype BackendKey BetterSqlBackend = BSQLKey { unBSQLKey :: BackendKey (Compatible SqlBackend BetterSqlBackend) }
    -- @
    --
    -- Then you can use @DerivingVia@ to automatically get instances like:
    --
    -- @
    -- deriving via BackendKey (Compatible SqlBackend BetterSqlBackend) instance Show (BackendKey BetterSqlBackend)
    -- ...
    -- @
    --
    -- These instances will go through the compatible backend's key (in this case,
    -- @'BackendKey' 'SqlBackend'@) for all their logic.
    newtype BackendKey (Compatible b s) = CompatibleKey { unCompatibleKey :: BackendKey b }

instance (HasPersistBackend b, BackendCompatible b s, PersistStoreRead b) => PersistStoreRead (Compatible b s) where
    get = withReaderT (projectBackend @b @s . unCompatible) . get
    getMany = withReaderT (projectBackend @b @s . unCompatible) . getMany

instance (HasPersistBackend b, BackendCompatible b s, PersistQueryRead b) => PersistQueryRead (Compatible b s) where
    selectSourceRes filts opts = withReaderT (projectBackend @b @s . unCompatible) $ selectSourceRes filts opts
    selectFirst filts opts = withReaderT (projectBackend @b @s . unCompatible) $ selectFirst filts opts
    selectKeysRes filts opts = withReaderT (projectBackend @b @s . unCompatible) $ selectKeysRes filts opts
    count = withReaderT (projectBackend @b @s . unCompatible) . count
    exists = withReaderT (projectBackend @b @s . unCompatible) . exists

instance (HasPersistBackend b, BackendCompatible b s, PersistQueryWrite b) => PersistQueryWrite (Compatible b s) where
    updateWhere filts updates = withReaderT (projectBackend @b @s . unCompatible) $ updateWhere filts updates
    deleteWhere = withReaderT (projectBackend @b @s . unCompatible) . deleteWhere

instance (HasPersistBackend b, BackendCompatible b s, PersistUniqueRead b) => PersistUniqueRead (Compatible b s) where
    getBy = withReaderT (projectBackend @b @s . unCompatible) . getBy
    existsBy = withReaderT (projectBackend @b @s . unCompatible) . existsBy

instance (HasPersistBackend b, BackendCompatible b s, PersistStoreWrite b) => PersistStoreWrite (Compatible b s) where
    insert = withReaderT (projectBackend @b @s . unCompatible) . insert
    insert_ = withReaderT (projectBackend @b @s . unCompatible) . insert_
    insertMany = withReaderT (projectBackend @b @s . unCompatible) . insertMany
    insertMany_ = withReaderT (projectBackend @b @s . unCompatible) . insertMany_
    insertEntityMany = withReaderT (projectBackend @b @s . unCompatible) . insertEntityMany
    insertKey k = withReaderT (projectBackend @b @s . unCompatible) . insertKey k
    repsert k = withReaderT (projectBackend @b @s . unCompatible) . repsert k
    repsertMany = withReaderT (projectBackend @b @s . unCompatible) . repsertMany
    replace k = withReaderT (projectBackend @b @s . unCompatible) . replace k
    delete = withReaderT (projectBackend @b @s . unCompatible) . delete
    update k = withReaderT (projectBackend @b @s . unCompatible) . update k
    updateGet k = withReaderT (projectBackend @b @s . unCompatible) . updateGet k

instance (HasPersistBackend b, BackendCompatible b s, PersistUniqueWrite b) => PersistUniqueWrite (Compatible b s) where
    deleteBy = withReaderT (projectBackend @b @s . unCompatible) . deleteBy
    insertUnique = withReaderT (projectBackend @b @s . unCompatible) . insertUnique
    upsert rec = withReaderT (projectBackend @b @s . unCompatible) . upsert rec
    upsertBy uniq rec = withReaderT (projectBackend @b @s . unCompatible) . upsertBy uniq rec
    putMany = withReaderT (projectBackend @b @s . unCompatible) . putMany

deriving via (BackendKey b) instance (BackendCompatible b s, Show (BackendKey b)) => Show (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Read (BackendKey b)) => Read (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Eq (BackendKey b)) => Eq (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Ord (BackendKey b)) => Ord (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Num (BackendKey b)) => Num (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Integral (BackendKey b)) => Integral (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, PersistField (BackendKey b)) => PersistField (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, PersistFieldSql (BackendKey b)) => PersistFieldSql (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Real (BackendKey b)) => Real (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Enum (BackendKey b)) => Enum (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, Bounded (BackendKey b)) => Bounded (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, ToJSON (BackendKey b)) => ToJSON (BackendKey (Compatible b s))
deriving via (BackendKey b) instance (BackendCompatible b s, FromJSON (BackendKey b)) => FromJSON (BackendKey (Compatible b s))