I'm trying to do something in Persistent with PostgreSQL that seems like it should be simple: Given a list of Attendance
records, overwrite any existing rows with same unique key or insert if they don't exist. Here are the types:
share [mkPersist sqlSettings, mkDeleteCascade sqlSettings, mkMigrate "migrateAllEvents"] [persistLowerCase|
Event json sql=events
description Text
date UTCTime
UniqueEvent date
Attendance json
attending Bool
eventId EventId
user UserId
UniqueAttendance eventId user
|]
I don't have keys, so I can't use repsert
, but I think upsert
is what I need. The documentation for upsert
looks a bit vague to me: If the record exists and I leave the updates blank, I understand that it will retain the entity as it was. But that's not equivalent to the behavior of repsert
, as claimed, is it? It also doesn't say what happens when no uniqueness constraint exists.
What I tried was
runDb (mapM_ ups atts)
where
-- ups rec = upsert rec [AttendanceAttending =. True] also doesn't work
ups rec = upsert rec [AttendanceAttending =. (attendanceAttending rec)]
but this leads to an error that I don't really understand:
• Illegal equational constraint BaseBackend backend ~ SqlBackend
(Use GADTs or TypeFamilies to permit this)
• When checking the inferred type
ups :: forall (m :: * -> *) backend.
(BaseBackend backend ~ SqlBackend, PersistUniqueWrite backend,
MonadIO m) =>
Attendance -> ReaderT backend m (Entity Attendance)
Any idea what causes this error? upsertBy
is also the same. I have imported Esqueleto in that same file, but hiding ((=.))
, so it should be pure Persistent.
Embarassingly, it really was as simple as adding {-# LANGUAGE TypeFamilies #-}
. I hadn't tried that because I misread the error message and none of my other modules needed that extension. Thanks, Fyodor!