composite-opaleye 0.4.2.0 → 0.5.0.0
raw patch · 6 files changed
+127/−5 lines, 6 filesdep +QuickCheckdep +composite-opaleyedep +hspecPVP ok
version bump matches the API change (PVP)
Dependencies added: QuickCheck, composite-opaleye, hspec
API changes (from Hackage documentation)
+ Composite.Opaleye.Update: class RecordToUpdate (rs :: [*]) (ss :: [*])
+ Composite.Opaleye.Update: instance Composite.Opaleye.Update.RecordToUpdate '[] '[]
+ Composite.Opaleye.Update: instance Composite.Opaleye.Update.RecordToUpdate rs ss => Composite.Opaleye.Update.RecordToUpdate (r : rs) (r : ss)
+ Composite.Opaleye.Update: instance Composite.Opaleye.Update.RecordToUpdate rs ss => Composite.Opaleye.Update.RecordToUpdate (s Composite.Record.:-> a : rs) (s Composite.Record.:-> GHC.Base.Maybe a : ss)
+ Composite.Opaleye.Update: recordToUpdate :: RecordToUpdate rs ss => Record rs -> Record ss
Files
- composite-opaleye.cabal +32/−3
- src/Composite/Opaleye.hs +2/−0
- src/Composite/Opaleye/RecordTable.hs +2/−2
- src/Composite/Opaleye/Update.hs +34/−0
- test/Main.hs +7/−0
- test/UpdateSpec.hs +50/−0
composite-opaleye.cabal view
@@ -1,9 +1,9 @@--- This file has been generated from package.yaml by hpack version 0.17.0.+-- This file has been generated from package.yaml by hpack version 0.18.1. -- -- see: https://github.com/sol/hpack name: composite-opaleye-version: 0.4.2.0+version: 0.5.0.0 synopsis: Opaleye SQL for Frames records description: Integration between Frames records and Opaleye SQL, allowing records to be stored, retrieved, and queried from PostgreSQL. category: Records@@ -18,7 +18,7 @@ library hs-source-dirs: src- default-extensions: DataKinds FlexibleContexts FlexibleInstances LambdaCase MultiParamTypeClasses OverloadedStrings PolyKinds ScopedTypeVariables StrictData TemplateHaskell TypeFamilies TypeOperators ViewPatterns+ default-extensions: DataKinds FlexibleContexts FlexibleInstances LambdaCase MultiParamTypeClasses OverloadedStrings PatternSynonyms PolyKinds ScopedTypeVariables StrictData TemplateHaskell TypeFamilies TypeOperators ViewPatterns ghc-options: -Wall -O2 build-depends: base >= 4.7 && < 5@@ -37,5 +37,34 @@ Composite.Opaleye.ProductProfunctors Composite.Opaleye.RecordTable Composite.Opaleye.TH+ Composite.Opaleye.Update Composite.Opaleye.Util+ other-modules:+ Paths_composite_opaleye+ default-language: Haskell2010++test-suite composite-opaleye-test+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs:+ test+ default-extensions: DataKinds FlexibleContexts FlexibleInstances LambdaCase MultiParamTypeClasses OverloadedStrings PatternSynonyms PolyKinds ScopedTypeVariables StrictData TemplateHaskell TypeFamilies TypeOperators ViewPatterns+ ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N -fno-warn-orphans+ build-depends:+ base >= 4.7 && < 5+ , bytestring+ , composite-base+ , lens+ , opaleye+ , postgresql-simple+ , product-profunctors+ , profunctors+ , template-haskell+ , text+ , vinyl+ , QuickCheck+ , composite-opaleye+ , hspec+ other-modules:+ UpdateSpec default-language: Haskell2010
src/Composite/Opaleye.hs view
@@ -1,7 +1,9 @@ module Composite.Opaleye ( module Composite.Opaleye.ProductProfunctors , module Composite.Opaleye.RecordTable+ , module Composite.Opaleye.Update ) where import Composite.Opaleye.ProductProfunctors import Composite.Opaleye.RecordTable+import Composite.Opaleye.Update
src/Composite/Opaleye/RecordTable.hs view
@@ -36,10 +36,10 @@ -- -- Is equivalent to: ----- > pReq (optional "id" &: required "name" &: Nil)+-- > pRec (optional "id" &: required "name" &: Nil) -- ----- Alternately, use 'Composite.Opaleye.ProductProfunctors.pReq' and the usual Opaleye 'required' and 'optional'.+-- Alternately, use 'Composite.Opaleye.ProductProfunctors.pRec' and the usual Opaleye 'required' and 'optional'. class DefaultRecTable write read where defaultRecTable :: TableProperties (Rec Identity write) (Rec Identity read)
+ src/Composite/Opaleye/Update.hs view
@@ -0,0 +1,34 @@+-- |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 #-}+
+ test/Main.hs view
@@ -0,0 +1,7 @@+import Test.Hspec (hspec)++import UpdateSpec (updateSuite)++main :: IO ()+main = hspec $ do+ updateSuite
+ test/UpdateSpec.hs view
@@ -0,0 +1,50 @@+module UpdateSpec where++import Composite.Opaleye.Update (recordToUpdate)+import Composite.Record ((:->), Rec(RNil), Record, pattern (:*:))+import Composite.TH (withLensesAndProxies)+import Test.Hspec (Spec, describe, it, shouldBe)++withLensesAndProxies [d|+ type FFoo = "foo" :-> Int+ type FFooMay = "foo" :-> Maybe Int+ type FBar = "bar" :-> String+ type FBaz = "baz" :-> Maybe Double+ type FBazMay = "baz" :-> Maybe (Maybe Double)+ type FQux = "qux" :-> Maybe Bool+ |]++type ForSelect1 = '[]+type ForUpdate1 = '[]++type ForSelect2 = '[FBar]+type ForUpdate2 = '[FBar]++type ForSelect3 = '[FFoo]+type ForUpdate3 = '[FFooMay]++type ForSelect4 = '[FFoo , FBar, FBaz , FQux]+type ForUpdate4 = '[FFooMay, FBar, FBazMay, FQux]++type ForSelect5 = '[FBar, FFoo , FQux, FBaz ]+type ForUpdate5 = '[FBar, FFooMay, FQux, FBazMay]++updateSuite :: Spec+updateSuite = do+ describe "Composite.Opaleye.Update" $ do+ it "should compute the update version of an empty record" $ do+ recordToUpdate ( RNil :: Record ForSelect1)+ `shouldBe` ( RNil :: Record ForUpdate1)+ it "should compute the update version of a record with no defaulted fields" $ do+ recordToUpdate ("hi" :*: RNil :: Record ForSelect2)+ `shouldBe` ("hi" :*: RNil :: Record ForUpdate2)+ it "should compute the update version of a record with a defaulted field" $ do+ recordToUpdate ( 123 :*: RNil :: Record ForSelect3)+ `shouldBe` (Just 123 :*: RNil :: Record ForUpdate3)+ it "should compute the update version of a record with mixed fields" $ do+ recordToUpdate ( 123 :*: "hi" :*: Nothing :*: Just True :*: RNil :: Record ForSelect4)+ `shouldBe` (Just 123 :*: "hi" :*: Just Nothing :*: Just True :*: RNil :: Record ForUpdate4)+ it "should compute the update version of a record with mixed fields and different ordering" $ do+ recordToUpdate ("hi" :*: 123 :*: Just True :*: Nothing :*: RNil :: Record ForSelect5)+ `shouldBe` ("hi" :*: Just 123 :*: Just True :*: Just Nothing :*: RNil :: Record ForUpdate5)+