-- |Module which provides utilities for processing updates using Opaleye and Composite module Composite.Opaleye.Update ( RecordToUpdate, recordToUpdate ) where import Composite.Record ((:->)(Val), Rec((:&), RNil), Record) import Data.Functor.Identity (Identity(Identity)) -- |Typeclass which allows transformation of a record from its select form to neutral update form, which boils down to wrapping fields that have defaults -- with 'Just'. class RecordToUpdate (rs :: [*]) (ss :: [*]) where -- |Transform a @'Record' rs@ obtained from the database to a @'Record' ss@ representing an updated version of the row. -- -- Opaleye's @runUpdate@ family of functions all take an update function of the type @columnsR -> columnsW@, which this function implements generically -- for a no-op update. -- -- Typically this function is composed with one or more lens @set@s which update the fields after the transformation. recordToUpdate :: Record rs -> Record ss -- |For an empty record, just act as 'id'. instance RecordToUpdate '[] '[] where recordToUpdate RNil = RNil {-# INLINE recordToUpdate #-} -- |For a field whose type doesn't change between selection and update, just pass the field unchanged and then recurse. instance RecordToUpdate rs ss => RecordToUpdate (r ': rs) (r ': ss) where recordToUpdate (r :& rs) = r :& recordToUpdate rs {-# INLINE recordToUpdate #-} -- |For a field whose type at selection is @s :-> a@ but at update is @s :-> Maybe a@ (a field which has a default value) add in a 'Just' and recurse. instance RecordToUpdate rs ss => RecordToUpdate (s :-> a ': rs) (s :-> Maybe a ': ss) where recordToUpdate (Identity (Val a) :& rs) = Identity (Val (Just a)) :& recordToUpdate rs {-# INLINE recordToUpdate #-}