haskellhaskell-persistent

Persistent upsert does not compile


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.


Solution

  • 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!