module UpsertTest where

import Data.Function (on)

import Init
import PersistentTestModels

-- | MongoDB assumes that a @NULL@ value in the database is some "empty"
-- value. So a query that does @+ 2@ to a @NULL@ value results in @2@. SQL
-- databases instead "annihilate" with null, so @NULL + 2 = NULL@.
data BackendNullUpdateBehavior
    = AssumeNullIsZero
    | Don'tUpdateNull

-- | @UPSERT@ on SQL databses does an "update-or-insert," which preserves
-- all prior values, including keys. MongoDB does not preserve the
-- identifier, so the entity key changes on an upsert.
data BackendUpsertKeyBehavior
    = UpsertGenerateNewKey
    | UpsertPreserveOldKey

specsWith
    :: forall backend m
     . (Runner backend m)
    => RunDb backend m
    -> BackendNullUpdateBehavior
    -> BackendUpsertKeyBehavior
    -> Spec
specsWith :: forall backend (m :: * -> *).
Runner backend m =>
RunDb backend m
-> BackendNullUpdateBehavior -> BackendUpsertKeyBehavior -> Spec
specsWith RunDb backend m
runDb BackendNullUpdateBehavior
handleNull BackendUpsertKeyBehavior
handleKey = String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"UpsertTests" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    let
        ifKeyIsPreserved :: ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved ReaderT backend m ()
expectation =
            case BackendUpsertKeyBehavior
handleKey of
                BackendUpsertKeyBehavior
UpsertGenerateNewKey -> () -> ReaderT backend m ()
forall a. a -> ReaderT backend m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                BackendUpsertKeyBehavior
UpsertPreserveOldKey -> ReaderT backend m ()
expectation

    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"upsert" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"adds a new row with no updates" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            Entity Key (UpsertGeneric backend)
_ UpsertGeneric backend
u <- UpsertGeneric backend
-> [Update (UpsertGeneric backend)]
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, OnlyOneUniqueKey record,
 SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 OnlyOneUniqueKey record, SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
upsert (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"new" Text
"" Int
2) [EntityField (UpsertGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertGeneric backend) typ
UpsertAttr EntityField (UpsertGeneric backend) Text
-> Text -> Update (UpsertGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"update"]
            Int
c <- [Filter (UpsertGeneric backend)] -> ReaderT backend m Int
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m Int
forall (m :: * -> *) record.
(MonadIO m, PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m Int
count ([] :: [Filter (UpsertGeneric backend)])
            Int
c Int -> Int -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Int
1
            UpsertGeneric backend -> Text
forall backend. UpsertGeneric backend -> Text
upsertAttr UpsertGeneric backend
u Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"new"
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"keeps the existing row" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            Entity Key (UpsertGeneric backend)
k0 UpsertGeneric backend
initial <- UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"initial" Text
"" Int
1)
            Entity Key (UpsertGeneric backend)
k1 UpsertGeneric backend
update' <- UpsertGeneric backend
-> [Update (UpsertGeneric backend)]
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, OnlyOneUniqueKey record,
 SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 OnlyOneUniqueKey record, SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
upsert (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"update" Text
"" Int
2) []
            UpsertGeneric backend
update' UpsertGeneric backend
-> UpsertGeneric backend -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== UpsertGeneric backend
initial
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Key (UpsertGeneric backend)
k0 Key (UpsertGeneric backend)
-> Key (UpsertGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Key (UpsertGeneric backend)
k1
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"updates an existing row - assignment" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            -- #ifdef WITH_MONGODB
            --         initial <- insertEntity (Upsert "cow" "initial" "extra" 1)
            --         update' <-
            --             upsert (Upsert "cow" "wow" "such unused" 2) [UpsertAttr =. "update"]
            --         ((==@) `on` entityKey) initial update'
            --         upsertAttr (entityVal update') @== "update"
            --         upsertExtra (entityVal update') @== "extra"
            -- #else
            Entity (UpsertGeneric backend)
initial <- UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"initial" Text
"extra" Int
1)
            Entity (UpsertGeneric backend)
update' <-
                UpsertGeneric backend
-> [Update (UpsertGeneric backend)]
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, OnlyOneUniqueKey record,
 SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 OnlyOneUniqueKey record, SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
upsert (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"wow" Text
"such unused" Int
2) [EntityField (UpsertGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertGeneric backend) typ
UpsertAttr EntityField (UpsertGeneric backend) Text
-> Text -> Update (UpsertGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"update"]
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ (Key (UpsertGeneric backend)
-> Key (UpsertGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
(==@) (Key (UpsertGeneric backend)
 -> Key (UpsertGeneric backend) -> ReaderT backend m ())
-> (Entity (UpsertGeneric backend) -> Key (UpsertGeneric backend))
-> Entity (UpsertGeneric backend)
-> Entity (UpsertGeneric backend)
-> ReaderT backend m ()
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Entity (UpsertGeneric backend) -> Key (UpsertGeneric backend)
forall record. Entity record -> Key record
entityKey) Entity (UpsertGeneric backend)
initial Entity (UpsertGeneric backend)
update'
            UpsertGeneric backend -> Text
forall backend. UpsertGeneric backend -> Text
upsertAttr (Entity (UpsertGeneric backend) -> UpsertGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertGeneric backend)
update') Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"update"
            UpsertGeneric backend -> Text
forall backend. UpsertGeneric backend -> Text
upsertExtra (Entity (UpsertGeneric backend) -> UpsertGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertGeneric backend)
update') Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"extra"
        -- #endif
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"updates existing row - addition " (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            -- #ifdef WITH_MONGODB
            --         initial <- insertEntity (Upsert "a1" "initial" "extra" 2)
            --         update' <-
            --             upsert (Upsert "a1" "wow" "such unused" 2) [UpsertAge +=. 3]
            --         ((==@) `on` entityKey) initial update'
            --         upsertAge (entityVal update') @== 5
            --         upsertExtra (entityVal update') @== "extra"
            -- #else
            Entity (UpsertGeneric backend)
initial <- UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"initial" Text
"extra" Int
2)
            Entity (UpsertGeneric backend)
update' <-
                UpsertGeneric backend
-> [Update (UpsertGeneric backend)]
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, OnlyOneUniqueKey record,
 SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 OnlyOneUniqueKey record, SafeToInsert record) =>
record -> [Update record] -> ReaderT backend m (Entity record)
upsert (Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
"a" Text
"wow" Text
"such unused" Int
2) [EntityField (UpsertGeneric backend) Int
forall backend typ.
(typ ~ Int) =>
EntityField (UpsertGeneric backend) typ
UpsertAge EntityField (UpsertGeneric backend) Int
-> Int -> Update (UpsertGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
+=. Int
3]
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ (Key (UpsertGeneric backend)
-> Key (UpsertGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
(==@) (Key (UpsertGeneric backend)
 -> Key (UpsertGeneric backend) -> ReaderT backend m ())
-> (Entity (UpsertGeneric backend) -> Key (UpsertGeneric backend))
-> Entity (UpsertGeneric backend)
-> Entity (UpsertGeneric backend)
-> ReaderT backend m ()
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Entity (UpsertGeneric backend) -> Key (UpsertGeneric backend)
forall record. Entity record -> Key record
entityKey) Entity (UpsertGeneric backend)
initial Entity (UpsertGeneric backend)
update'
            UpsertGeneric backend -> Int
forall backend. UpsertGeneric backend -> Int
upsertAge (Entity (UpsertGeneric backend) -> UpsertGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertGeneric backend)
update') Int -> Int -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Int
5
            UpsertGeneric backend -> Text
forall backend. UpsertGeneric backend -> Text
upsertExtra (Entity (UpsertGeneric backend) -> UpsertGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertGeneric backend)
update') Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"extra"
    -- #endif

    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"upsertBy" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
        let
            uniqueEmail :: Unique (UpsertByGeneric backend)
uniqueEmail = Text -> Unique (UpsertByGeneric backend)
forall backend. Text -> Unique (UpsertByGeneric backend)
UniqueUpsertBy Text
"a"
            _uniqueCity :: Unique (UpsertByGeneric backend)
_uniqueCity = Text -> Unique (UpsertByGeneric backend)
forall backend. Text -> Unique (UpsertByGeneric backend)
UniqueUpsertByCity Text
"Boston"
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"adds a new row with no updates" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            Entity Key (UpsertByGeneric backend)
_ UpsertByGeneric backend
u <-
                Unique (UpsertByGeneric backend)
-> UpsertByGeneric backend
-> [Update (UpsertByGeneric backend)]
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
upsertBy
                    Unique (UpsertByGeneric backend)
forall {backend}. Unique (UpsertByGeneric backend)
uniqueEmail
                    (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"a" Text
"Boston" Text
"new")
                    [EntityField (UpsertByGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertByGeneric backend) typ
UpsertByAttr EntityField (UpsertByGeneric backend) Text
-> Text -> Update (UpsertByGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"update"]
            Int
c <- [Filter (UpsertByGeneric backend)] -> ReaderT backend m Int
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m Int
forall (m :: * -> *) record.
(MonadIO m, PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m Int
count ([] :: [Filter (UpsertByGeneric backend)])
            Int
c Int -> Int -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Int
1
            UpsertByGeneric backend -> Text
forall backend. UpsertByGeneric backend -> Text
upsertByAttr UpsertByGeneric backend
u Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"new"
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"keeps the existing row" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            Entity Key (UpsertByGeneric backend)
k0 UpsertByGeneric backend
initial <- UpsertByGeneric backend
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"a" Text
"Boston" Text
"initial")
            Entity Key (UpsertByGeneric backend)
k1 UpsertByGeneric backend
update' <- Unique (UpsertByGeneric backend)
-> UpsertByGeneric backend
-> [Update (UpsertByGeneric backend)]
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
upsertBy Unique (UpsertByGeneric backend)
forall {backend}. Unique (UpsertByGeneric backend)
uniqueEmail (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"a" Text
"Boston" Text
"update") []
            UpsertByGeneric backend
update' UpsertByGeneric backend
-> UpsertByGeneric backend -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== UpsertByGeneric backend
initial
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Key (UpsertByGeneric backend)
k0 Key (UpsertByGeneric backend)
-> Key (UpsertByGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Key (UpsertByGeneric backend)
k1
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"updates an existing row" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            -- #ifdef WITH_MONGODB
            --         initial <- insertEntity (UpsertBy "ko" "Kumbakonam" "initial")
            --         update' <-
            --             upsertBy
            --                 (UniqueUpsertBy "ko")
            --                 (UpsertBy "ko" "Bangalore" "such unused")
            --                 [UpsertByAttr =. "update"]
            --         ((==@) `on` entityKey) initial update'
            --         upsertByAttr (entityVal update') @== "update"
            --         upsertByCity (entityVal update') @== "Kumbakonam"
            -- #else
            Entity (UpsertByGeneric backend)
initial <- UpsertByGeneric backend
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"a" Text
"Boston" Text
"initial")
            Entity (UpsertByGeneric backend)
update' <-
                Unique (UpsertByGeneric backend)
-> UpsertByGeneric backend
-> [Update (UpsertByGeneric backend)]
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
upsertBy
                    Unique (UpsertByGeneric backend)
forall {backend}. Unique (UpsertByGeneric backend)
uniqueEmail
                    (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"a" Text
"wow" Text
"such unused")
                    [EntityField (UpsertByGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertByGeneric backend) typ
UpsertByAttr EntityField (UpsertByGeneric backend) Text
-> Text -> Update (UpsertByGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"update"]
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ (Key (UpsertByGeneric backend)
-> Key (UpsertByGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
(==@) (Key (UpsertByGeneric backend)
 -> Key (UpsertByGeneric backend) -> ReaderT backend m ())
-> (Entity (UpsertByGeneric backend)
    -> Key (UpsertByGeneric backend))
-> Entity (UpsertByGeneric backend)
-> Entity (UpsertByGeneric backend)
-> ReaderT backend m ()
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Entity (UpsertByGeneric backend) -> Key (UpsertByGeneric backend)
forall record. Entity record -> Key record
entityKey) Entity (UpsertByGeneric backend)
initial Entity (UpsertByGeneric backend)
update'
            UpsertByGeneric backend -> Text
forall backend. UpsertByGeneric backend -> Text
upsertByAttr (Entity (UpsertByGeneric backend) -> UpsertByGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertByGeneric backend)
update') Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"update"
            UpsertByGeneric backend -> Text
forall backend. UpsertByGeneric backend -> Text
upsertByCity (Entity (UpsertByGeneric backend) -> UpsertByGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertByGeneric backend)
update') Text -> Text -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text
"Boston"
        -- #endif
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"updates by the appropriate constraint" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            Entity (UpsertByGeneric backend)
initBoston <- UpsertByGeneric backend
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"bos" Text
"Boston" Text
"bos init")
            Entity (UpsertByGeneric backend)
initKrum <- UpsertByGeneric backend
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"krum" Text
"Krum" Text
"krum init")
            Entity (UpsertByGeneric backend)
updBoston <-
                Unique (UpsertByGeneric backend)
-> UpsertByGeneric backend
-> [Update (UpsertByGeneric backend)]
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
upsertBy
                    (Text -> Unique (UpsertByGeneric backend)
forall backend. Text -> Unique (UpsertByGeneric backend)
UniqueUpsertBy Text
"bos")
                    (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"bos" Text
"Krum" Text
"unused")
                    [EntityField (UpsertByGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertByGeneric backend) typ
UpsertByAttr EntityField (UpsertByGeneric backend) Text
-> Text -> Update (UpsertByGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"bos update"]
            Entity (UpsertByGeneric backend)
updKrum <-
                Unique (UpsertByGeneric backend)
-> UpsertByGeneric backend
-> [Update (UpsertByGeneric backend)]
-> ReaderT backend m (Entity (UpsertByGeneric backend))
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
Unique record
-> record -> [Update record] -> ReaderT backend m (Entity record)
upsertBy
                    (Text -> Unique (UpsertByGeneric backend)
forall backend. Text -> Unique (UpsertByGeneric backend)
UniqueUpsertByCity Text
"Krum")
                    (Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"bos" Text
"Krum" Text
"unused")
                    [EntityField (UpsertByGeneric backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (UpsertByGeneric backend) typ
UpsertByAttr EntityField (UpsertByGeneric backend) Text
-> Text -> Update (UpsertByGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. Text
"krum update"]
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ (Key (UpsertByGeneric backend)
-> Key (UpsertByGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
(==@) (Key (UpsertByGeneric backend)
 -> Key (UpsertByGeneric backend) -> ReaderT backend m ())
-> (Entity (UpsertByGeneric backend)
    -> Key (UpsertByGeneric backend))
-> Entity (UpsertByGeneric backend)
-> Entity (UpsertByGeneric backend)
-> ReaderT backend m ()
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Entity (UpsertByGeneric backend) -> Key (UpsertByGeneric backend)
forall record. Entity record -> Key record
entityKey) Entity (UpsertByGeneric backend)
initBoston Entity (UpsertByGeneric backend)
updBoston
            ReaderT backend m () -> ReaderT backend m ()
ifKeyIsPreserved (ReaderT backend m () -> ReaderT backend m ())
-> ReaderT backend m () -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ (Key (UpsertByGeneric backend)
-> Key (UpsertByGeneric backend) -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
(==@) (Key (UpsertByGeneric backend)
 -> Key (UpsertByGeneric backend) -> ReaderT backend m ())
-> (Entity (UpsertByGeneric backend)
    -> Key (UpsertByGeneric backend))
-> Entity (UpsertByGeneric backend)
-> Entity (UpsertByGeneric backend)
-> ReaderT backend m ()
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Entity (UpsertByGeneric backend) -> Key (UpsertByGeneric backend)
forall record. Entity record -> Key record
entityKey) Entity (UpsertByGeneric backend)
initKrum Entity (UpsertByGeneric backend)
updKrum
            Entity (UpsertByGeneric backend) -> UpsertByGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertByGeneric backend)
updBoston UpsertByGeneric backend
-> UpsertByGeneric backend -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"bos" Text
"Boston" Text
"bos update"
            Entity (UpsertByGeneric backend) -> UpsertByGeneric backend
forall record. Entity record -> record
entityVal Entity (UpsertByGeneric backend)
updKrum UpsertByGeneric backend
-> UpsertByGeneric backend -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== Text -> Text -> Text -> UpsertByGeneric backend
forall backend. Text -> Text -> Text -> UpsertByGeneric backend
UpsertBy Text
"krum" Text
"Krum" Text
"krum update"

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"maybe update" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
        let
            noAge :: PersonMaybeAgeGeneric backend
noAge = Text -> Maybe Int -> PersonMaybeAgeGeneric backend
forall backend. Text -> Maybe Int -> PersonMaybeAgeGeneric backend
PersonMaybeAge Text
"Michael" Maybe Int
forall a. Maybe a
Nothing
        Key (PersonMaybeAgeGeneric backend)
keyNoAge <- PersonMaybeAgeGeneric backend
-> ReaderT backend m (Key (PersonMaybeAgeGeneric backend))
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
record -> ReaderT backend m (Key record)
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
record -> ReaderT backend m (Key record)
insert PersonMaybeAgeGeneric backend
forall {backend}. PersonMaybeAgeGeneric backend
noAge
        PersonMaybeAgeGeneric backend
noAge2 <- Key (PersonMaybeAgeGeneric backend)
-> [Update (PersonMaybeAgeGeneric backend)]
-> ReaderT backend m (PersonMaybeAgeGeneric backend)
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> [Update record] -> ReaderT backend m record
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Key record -> [Update record] -> ReaderT backend m record
updateGet Key (PersonMaybeAgeGeneric backend)
keyNoAge [EntityField (PersonMaybeAgeGeneric backend) (Maybe Int)
forall backend typ.
(typ ~ Maybe Int) =>
EntityField (PersonMaybeAgeGeneric backend) typ
PersonMaybeAgeAge EntityField (PersonMaybeAgeGeneric backend) (Maybe Int)
-> Maybe Int -> Update (PersonMaybeAgeGeneric backend)
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
+=. Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2]
        -- the correct answer depends on the backend. MongoDB assumes
        -- a 'Nothing' value is 0, and does @0 + 2@ for @Just 2@. In a SQL
        -- database, @NULL@ annihilates, so @NULL + 2 = NULL@.
        PersonMaybeAgeGeneric backend -> Maybe Int
forall backend. PersonMaybeAgeGeneric backend -> Maybe Int
personMaybeAgeAge PersonMaybeAgeGeneric backend
noAge2 Maybe Int -> Maybe Int -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== case BackendNullUpdateBehavior
handleNull of
            BackendNullUpdateBehavior
AssumeNullIsZero ->
                Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2
            BackendNullUpdateBehavior
Don'tUpdateNull ->
                Maybe Int
forall a. Maybe a
Nothing

    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"putMany" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"adds new rows when entity has no unique constraints" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            let
                mkPerson :: Text -> Person1Generic backend
mkPerson Text
name_ = Text -> Int -> Person1Generic backend
forall backend. Text -> Int -> Person1Generic backend
Person1 Text
name_ Int
25
            let
                names :: [Text]
names = [Text
"putMany bob", Text
"putMany bob", Text
"putMany smith"]
            let
                records :: [Person1Generic backend]
records = (Text -> Person1Generic backend)
-> [Text] -> [Person1Generic backend]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Person1Generic backend
forall {backend}. Text -> Person1Generic backend
mkPerson [Text]
names
            ()
_ <- [Person1Generic backend] -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
[record] -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
[record] -> ReaderT backend m ()
putMany [Person1Generic backend]
records
            [Entity (Person1Generic backend)]
entitiesDb <- [Filter (Person1Generic backend)]
-> [SelectOpt (Person1Generic backend)]
-> ReaderT backend m [Entity (Person1Generic backend)]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList [EntityField (Person1Generic backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (Person1Generic backend) typ
Person1Name EntityField (Person1Generic backend) Text
-> [Text] -> Filter (Person1Generic backend)
forall v typ.
PersistField typ =>
EntityField v typ -> [typ] -> Filter v
<-. [Text]
names] []
            let
                recordsDb :: [Person1Generic backend]
recordsDb = (Entity (Person1Generic backend) -> Person1Generic backend)
-> [Entity (Person1Generic backend)] -> [Person1Generic backend]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Entity (Person1Generic backend) -> Person1Generic backend
forall record. Entity record -> record
entityVal [Entity (Person1Generic backend)]
entitiesDb
            [Person1Generic backend]
recordsDb [Person1Generic backend]
-> [Person1Generic backend] -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== [Person1Generic backend]
records
            [Filter (Person1Generic backend)] -> ReaderT backend m ()
forall backend (m :: * -> *) record.
(PersistQueryWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m ()
forall (m :: * -> *) record.
(MonadIO m, PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m ()
deleteWhere [EntityField (Person1Generic backend) Text
forall backend typ.
(typ ~ Text) =>
EntityField (Person1Generic backend) typ
Person1Name EntityField (Person1Generic backend) Text
-> [Text] -> Filter (Person1Generic backend)
forall v typ.
PersistField typ =>
EntityField v typ -> [typ] -> Filter v
<-. [Text]
names]
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"adds new rows when no conflicts" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            let
                mkUpsert :: Text -> UpsertGeneric backend
mkUpsert Text
e = Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
e Text
"new" Text
"" Int
1
            let
                keys :: [Text]
keys = [Text
"putMany1", Text
"putMany2", Text
"putMany3"]
            let
                vals :: [UpsertGeneric backend]
vals = (Text -> UpsertGeneric backend)
-> [Text] -> [UpsertGeneric backend]
forall a b. (a -> b) -> [a] -> [b]
map Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert [Text]
keys
            ()
_ <- [UpsertGeneric backend] -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
[record] -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
[record] -> ReaderT backend m ()
putMany [UpsertGeneric backend]
vals
            Just (Entity Key (UpsertGeneric backend)
_ UpsertGeneric backend
v1) <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany1"
            Just (Entity Key (UpsertGeneric backend)
_ UpsertGeneric backend
v2) <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany2"
            Just (Entity Key (UpsertGeneric backend)
_ UpsertGeneric backend
v3) <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany3"
            [UpsertGeneric backend
v1, UpsertGeneric backend
v2, UpsertGeneric backend
v3] [UpsertGeneric backend]
-> [UpsertGeneric backend] -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== [UpsertGeneric backend]
vals
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany1"
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany2"
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany3"
        String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"handles conflicts by replacing old keys with new records" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ RunDb backend m
runDb RunDb backend m -> RunDb backend m
forall a b. (a -> b) -> a -> b
$ do
            let
                mkUpsert1 :: Text -> UpsertGeneric backend
mkUpsert1 Text
e = Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
e Text
"new" Text
"" Int
1
            let
                mkUpsert2 :: Text -> UpsertGeneric backend
mkUpsert2 Text
e = Text -> Text -> Text -> Int -> UpsertGeneric backend
forall backend.
Text -> Text -> Text -> Int -> UpsertGeneric backend
Upsert Text
e Text
"new" Text
"" Int
2
            let
                vals :: [UpsertGeneric backend]
vals = (Text -> UpsertGeneric backend)
-> [Text] -> [UpsertGeneric backend]
forall a b. (a -> b) -> [a] -> [b]
map Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert2 [Text
"putMany4", Text
"putMany5", Text
"putMany6", Text
"putMany7"]
            Entity Key (UpsertGeneric backend)
k1 UpsertGeneric backend
_ <- UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (UpsertGeneric backend
 -> ReaderT backend m (Entity (UpsertGeneric backend)))
-> UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall a b. (a -> b) -> a -> b
$ Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert1 Text
"putMany4"
            Entity Key (UpsertGeneric backend)
k2 UpsertGeneric backend
_ <- UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall e backend (m :: * -> *).
(PersistStoreWrite backend, PersistRecordBackend e backend,
 SafeToInsert e, MonadIO m, HasCallStack) =>
e -> ReaderT backend m (Entity e)
insertEntity (UpsertGeneric backend
 -> ReaderT backend m (Entity (UpsertGeneric backend)))
-> UpsertGeneric backend
-> ReaderT backend m (Entity (UpsertGeneric backend))
forall a b. (a -> b) -> a -> b
$ Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert1 Text
"putMany5"
            ()
_ <- [UpsertGeneric backend] -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend, SafeToInsert record) =>
[record] -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend,
 SafeToInsert record) =>
[record] -> ReaderT backend m ()
putMany ([UpsertGeneric backend] -> ReaderT backend m ())
-> [UpsertGeneric backend] -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert1 Text
"putMany4" UpsertGeneric backend
-> [UpsertGeneric backend] -> [UpsertGeneric backend]
forall a. a -> [a] -> [a]
: [UpsertGeneric backend]
forall {backend}. [UpsertGeneric backend]
vals
            Just Entity (UpsertGeneric backend)
e1 <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany4"
            Just Entity (UpsertGeneric backend)
e2 <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany5"
            Just e3 :: Entity (UpsertGeneric backend)
e3@(Entity Key (UpsertGeneric backend)
k3 UpsertGeneric backend
_) <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany6"
            Just e4 :: Entity (UpsertGeneric backend)
e4@(Entity Key (UpsertGeneric backend)
k4 UpsertGeneric backend
_) <- Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall backend record (m :: * -> *).
(PersistUniqueRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m (Maybe (Entity record))
getBy (Unique (UpsertGeneric backend)
 -> ReaderT backend m (Maybe (Entity (UpsertGeneric backend))))
-> Unique (UpsertGeneric backend)
-> ReaderT backend m (Maybe (Entity (UpsertGeneric backend)))
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany7"

            [Entity (UpsertGeneric backend)
e1, Entity (UpsertGeneric backend)
e2, Entity (UpsertGeneric backend)
e3, Entity (UpsertGeneric backend)
e4]
                [Entity (UpsertGeneric backend)]
-> [Entity (UpsertGeneric backend)] -> ReaderT backend m ()
forall a (m :: * -> *).
(HasCallStack, Eq a, Show a, MonadIO m) =>
a -> a -> m ()
@== [ Key (UpsertGeneric backend)
-> UpsertGeneric backend -> Entity (UpsertGeneric backend)
forall record. Key record -> record -> Entity record
Entity Key (UpsertGeneric backend)
k1 (Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert2 Text
"putMany4")
                    , Key (UpsertGeneric backend)
-> UpsertGeneric backend -> Entity (UpsertGeneric backend)
forall record. Key record -> record -> Entity record
Entity Key (UpsertGeneric backend)
k2 (Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert2 Text
"putMany5")
                    , Key (UpsertGeneric backend)
-> UpsertGeneric backend -> Entity (UpsertGeneric backend)
forall record. Key record -> record -> Entity record
Entity Key (UpsertGeneric backend)
k3 (Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert2 Text
"putMany6")
                    , Key (UpsertGeneric backend)
-> UpsertGeneric backend -> Entity (UpsertGeneric backend)
forall record. Key record -> record -> Entity record
Entity Key (UpsertGeneric backend)
k4 (Text -> UpsertGeneric backend
forall {backend}. Text -> UpsertGeneric backend
mkUpsert2 Text
"putMany7")
                    ]
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany4"
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany5"
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany6"
            Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistUniqueWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
forall record (m :: * -> *).
(MonadIO m, PersistRecordBackend record backend) =>
Unique record -> ReaderT backend m ()
deleteBy (Unique (UpsertGeneric backend) -> ReaderT backend m ())
-> Unique (UpsertGeneric backend) -> ReaderT backend m ()
forall a b. (a -> b) -> a -> b
$ Text -> Unique (UpsertGeneric backend)
forall backend. Text -> Unique (UpsertGeneric backend)
UniqueUpsert Text
"putMany7"