packages feed

opaleye 0.7.4.0 → 0.7.5.0

raw patch · 12 files changed

+229/−21 lines, 12 filesdep +time-compatdep ~timePVP ok

version bump matches the API change (PVP)

Dependencies added: time-compat

Dependency ranges changed: time

API changes (from Hackage documentation)

+ Opaleye.Experimental.Enum: enumMapperWithSchema :: String -> String -> (String -> Maybe haskellSum) -> (haskellSum -> String) -> EnumMapper sqlEnum haskellSum
+ Opaleye.Internal.Constant: instance Data.Profunctor.Product.Default.Class.Default Opaleye.Internal.Constant.ToFields Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime (Opaleye.Internal.Column.Column Opaleye.Internal.PGTypesExternal.SqlInterval)
+ Opaleye.Internal.Inferrable: instance (Opaleye.Internal.Column.Column Opaleye.Internal.PGTypesExternal.SqlInterval GHC.Types.~ cSqlInterval) => Data.Profunctor.Product.Default.Class.Default (Opaleye.Internal.Inferrable.Inferrable Opaleye.Internal.Constant.ToFields) Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime cSqlInterval
+ Opaleye.Internal.Inferrable: instance (calendardifftime GHC.Types.~ Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime) => Data.Profunctor.Product.Default.Class.Default (Opaleye.Internal.Inferrable.Inferrable Opaleye.Internal.RunQuery.FromField) Opaleye.Internal.PGTypesExternal.SqlInterval calendardifftime
+ Opaleye.Internal.PGTypesExternal: data SqlInterval
+ Opaleye.Internal.PGTypesExternal: instance Opaleye.Internal.PGTypes.IsSqlType Opaleye.Internal.PGTypesExternal.SqlInterval
+ Opaleye.Internal.PGTypesExternal: sqlInterval :: CalendarDiffTime -> Column PGInterval
+ Opaleye.Internal.PGTypesExternal: type PGInterval = SqlInterval
+ Opaleye.Internal.RunQuery: instance Opaleye.Internal.RunQuery.DefaultFromField Opaleye.Internal.PGTypesExternal.SqlInterval Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime
+ Opaleye.Operators: addInterval :: IntervalNum from to => Field from -> Field SqlInterval -> Field to
+ Opaleye.Operators: class IntervalNum from to | from -> to
+ Opaleye.Operators: instance Opaleye.Operators.IntervalNum Opaleye.Internal.PGTypesExternal.SqlDate Opaleye.Internal.PGTypesExternal.SqlTimestamp
+ Opaleye.Operators: instance Opaleye.Operators.IntervalNum Opaleye.Internal.PGTypesExternal.SqlInterval Opaleye.Internal.PGTypesExternal.SqlInterval
+ Opaleye.Operators: instance Opaleye.Operators.IntervalNum Opaleye.Internal.PGTypesExternal.SqlTime Opaleye.Internal.PGTypesExternal.SqlTime
+ Opaleye.Operators: instance Opaleye.Operators.IntervalNum Opaleye.Internal.PGTypesExternal.SqlTimestamp Opaleye.Internal.PGTypesExternal.SqlTimestamp
+ Opaleye.Operators: instance Opaleye.Operators.IntervalNum Opaleye.Internal.PGTypesExternal.SqlTimestamptz Opaleye.Internal.PGTypesExternal.SqlTimestamptz
+ Opaleye.Operators: minusInterval :: IntervalNum from to => Field from -> Field SqlInterval -> Field to
+ Opaleye.SqlTypes: data SqlInterval
+ Opaleye.SqlTypes: sqlInterval :: CalendarDiffTime -> Column PGInterval

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## 0.7.5.0++* Added `enumMapperWithSchema`.  Thanks to Steve Mao.++* Added `SqlInterval`.  Thanks to Bas van Dijk.+ ## 0.7.4.0  * Added `distinctOnCorrect` and `distinctOnByCorrect` which will
Doc/Tutorial/TutorialBasic.lhs view
@@ -9,11 +9,11 @@ > > import           Opaleye (Field, FieldNullable, matchNullable, isNull, >                          Table, table, tableField, selectTable,->                          Select, restrict, (.==), (.<=), (.&&), (.<),+>                          Select, (.==), (.<=), (.&&), (.<), >                          (.===), >                          (.++), ifThenElse, sqlString, aggregate, groupBy, >                          count, avg, sum, leftJoin, runSelect,->                          showSql, viaLateral, Unpackspec,+>                          showSql, where_, Unpackspec, >                          SqlInt4, SqlInt8, SqlText, SqlDate, SqlFloat8, SqlBool) > > import           Data.Profunctor.Product (p2, p3)@@ -253,7 +253,7 @@ > youngPeople :: Select (Field SqlText, Field SqlInt4, Field SqlText) > youngPeople = do >   row@(_, age, _) <- personSelect->   viaLateral restrict (age .<= 18)+>   where_ (age .<= 18) > >   pure row @@ -284,8 +284,8 @@ > twentiesAtAddress = do >   row@(_, age, address) <- personSelect >->   viaLateral restrict $ (20 .<= age) .&& (age .< 30)->   viaLateral restrict $ address .== sqlString "1 My Street, My Town"+>   where_ $ (20 .<= age) .&& (age .< 30)+>   where_ $ address .== sqlString "1 My Street, My Town" > >   pure row @@ -326,7 +326,7 @@ >   (name, age, address) <- personSelect >   birthday             <- birthdaySelect >->   viaLateral restrict $ name .== bdName birthday+>   where_ $ name .== bdName birthday > >   pure (name, age, address, bdDay birthday) @@ -470,11 +470,11 @@  > restrictIsTwenties :: Field SqlInt4 -> Select () > restrictIsTwenties age = do->   viaLateral restrict $ (20 .<= age) .&& (age .< 30)+>   where_ $ (20 .<= age) .&& (age .< 30) > > restrictAddressIs1MyStreet :: Field SqlText -> Select () > restrictAddressIs1MyStreet address = do->   viaLateral restrict $ address .== sqlString "1 My Street, My Town"+>   where_ $ address .== sqlString "1 My Street, My Town"  We can't generate "the SQL of" these combinators.  They are not `Select`s so they don't have any SQL!  (This corresponds to the@@ -517,7 +517,7 @@ > birthdayOfPerson name = do >   birthday <- birthdaySelect >->   viaLateral restrict $ name .== bdName birthday+>   where_ $ name .== bdName birthday > >   pure (bdDay birthday) 
Test/Test.hs view
@@ -21,7 +21,8 @@ import qualified Data.String                      as String import qualified Data.ByteString                  as SBS import qualified Data.Text                        as T-import qualified Data.Time                        as Time+import qualified Data.Time.Compat                 as Time+import qualified Data.Time.Clock.POSIX.Compat     as Time import qualified Database.PostgreSQL.Simple       as PGS import qualified Database.PostgreSQL.Simple.Range as R import           GHC.Int                          (Int64)@@ -1255,6 +1256,8 @@     testH (pure (O.sqlZonedTime value))           (\r -> map Time.zonedTimeToUTC r `shouldBe` [Time.zonedTimeToUTC value]) +  it "sqlInterval" $ testLiteral O.sqlInterval (Time.calendarTimeTime 1)+ -- Check that MaybeFields's "Nothings" are not distinct, even if we -- fmap different values over their inner fields. testMaybeFieldsDistinct :: Test@@ -1274,7 +1277,108 @@   it "Returns same rows from a table" $       testH (OL.forUpdate table1Q) (`shouldBe` table1data) +testAddIntervalFromDateToTimestamptz :: Test+testAddIntervalFromDateToTimestamptz = do+  it "date + interval = timestamptz" $ testH query (`shouldBe` [expectation])+  where query :: Select (Field O.SqlTimestamp)+        query = pure $ (O.toFields d :: Field O.SqlDate)+                       `O.addInterval`+                       (O.toFields c :: Field O.SqlInterval) +        d :: Time.Day+        d = Time.ModifiedJulianDay 0 -- = 1858-11-17++        -- 1 second+        c :: Time.CalendarDiffTime+        c = Time.calendarTimeTime 1++        expectation :: Time.LocalTime+        expectation = Time.ctTime c `Time.addLocalTime`+                        Time.LocalTime+                        { Time.localDay = d+                        , Time.localTimeOfDay = Time.TimeOfDay 0 0 0+                        }++testAddIntervalFromIntervalToInterval :: Test+testAddIntervalFromIntervalToInterval = do+  it "interval + interval = interval" $ testH query (`shouldBe` [expectation])+  where query :: Select (Field O.SqlInterval)+        query = pure $ (O.toFields c1 :: Field O.SqlInterval)+                       `O.addInterval`+                       (O.toFields c2 :: Field O.SqlInterval)++        -- 1 second+        c1 :: Time.CalendarDiffTime+        c1 = Time.calendarTimeTime 1++        -- 2 second+        c2 :: Time.CalendarDiffTime+        c2 = Time.calendarTimeTime 2++        expectation :: Time.CalendarDiffTime+        expectation = Time.calendarTimeTime $ Time.ctTime c1 + Time.ctTime c2++testAddIntervalFromTimestampToTimestamp :: Test+testAddIntervalFromTimestampToTimestamp = do+  it "timestamp + interval = timestamp" $ testH query (`shouldBe` [expectation])+  where query :: Select (Field O.SqlTimestamp)+        query = pure $ (O.toFields t :: Field O.SqlTimestamp)+                       `O.addInterval`+                       (O.toFields c :: Field O.SqlInterval)++        t :: Time.LocalTime+        t = Time.LocalTime+            { Time.localDay = Time.ModifiedJulianDay 0 -- = 1858-11-17+            , Time.localTimeOfDay = Time.TimeOfDay 0 0 0 -- midnight+            }++        -- 1 second+        c :: Time.CalendarDiffTime+        c = Time.calendarTimeTime 1++        expectation :: Time.LocalTime+        expectation = Time.ctTime c `Time.addLocalTime` t++testAddIntervalFromTimestamptzToTimestamptz :: Test+testAddIntervalFromTimestamptzToTimestamptz = do+  it "timestamptz + interval = timestamptz" $ testH query (`shouldBe` [expectation])+  where query :: Select (Field O.SqlTimestamptz)+        query = pure $ (O.toFields t :: Field O.SqlTimestamptz)+                       `O.addInterval`+                       (O.toFields c :: Field O.SqlInterval)++        -- UNIX epoch+        t :: Time.UTCTime+        t = Time.posixSecondsToUTCTime 0++        -- 1 second+        c :: Time.CalendarDiffTime+        c = Time.calendarTimeTime 1++        expectation :: Time.UTCTime+        expectation = Time.ctTime c `Time.addUTCTime` t++testAddIntervalFromTimeToTime :: Test+testAddIntervalFromTimeToTime = do+  it "time + interval = time" $ testH query (`shouldBe` [expectation])+  where query :: Select (Field O.SqlTime)+        query = pure $ (O.toFields t :: Field O.SqlTime)+                       `O.addInterval`+                       (O.toFields c :: Field O.SqlInterval)++        -- midnight+        t :: Time.TimeOfDay+        t = Time.TimeOfDay 0 0 0++        -- 1 second+        c :: Time.CalendarDiffTime+        c = Time.calendarTimeTime 1++        expectation :: Time.TimeOfDay+        expectation = Time.timeToTimeOfDay $+                        (realToFrac (Time.ctTime c :: Time.NominalDiffTime) :: Time.DiffTime)+                          + Time.timeOfDayToTime t+ main :: IO () main = do   let envVarName = "POSTGRES_CONNSTRING"@@ -1323,6 +1427,9 @@   Connection.close conn2    conn3 <- PGS.connectPostgreSQL connectString+  -- intervals can only be decoded to CalendarDiffTimes+  -- when the interval rendering style is set to ISO-8601.+  _nrOfAffectedRows <- PGS.execute_ conn3 "SET intervalstyle TO iso_8601;"   hspec $ do     before (return conn3) $ do       describe "core dsl?" $ do@@ -1428,3 +1535,9 @@         testMaybeFieldsDistinct       describe "Locking" $ do         testForUpdate+      describe "Interval" $ do+        testAddIntervalFromDateToTimestamptz+        testAddIntervalFromIntervalToInterval+        testAddIntervalFromTimestampToTimestamp+        testAddIntervalFromTimestamptzToTimestamptz+        testAddIntervalFromTimeToTime
opaleye.cabal view
@@ -1,6 +1,6 @@ name:            opaleye copyright:       Copyright (c) 2014-2018 Purely Agile Limited; 2019-2021 Tom Ellis-version:         0.7.4.0+version:         0.7.5.0 synopsis:        An SQL-generating DSL targeting PostgreSQL description:     An SQL-generating DSL targeting PostgreSQL.  Allows                  Postgres queries to be written within Haskell in a@@ -41,7 +41,7 @@     , semigroups          >= 0.13    && < 0.20     , text                >= 0.11    && < 1.3     , transformers        >= 0.3     && < 0.6-    , time                >= 1.4     && < 1.10+    , time-compat         >= 1.9.5   && < 1.12     , time-locale-compat  >= 0.1     && < 0.2     , uuid                >= 1.3     && < 1.4     , void                >= 0.4     && < 0.8@@ -141,7 +141,7 @@     QuickCheck,     semigroups,     text >= 0.11 && < 1.3,-    time,+    time-compat,     uuid,     transformers,     hspec,
src/Opaleye/Experimental/Enum.hs view
@@ -5,6 +5,7 @@   (     enumMapper,     EnumMapper,+    enumMapperWithSchema,     enumFromField,     enumToFields,     fromFieldToFieldsEnum,@@ -17,6 +18,8 @@  import           Data.ByteString.Char8 (unpack) import qualified Data.Profunctor.Product.Default as D+import Text.PrettyPrint.HughesPJ ((<>), doubleQuotes, render, text)+import Prelude hiding ((<>))  data EnumMapper sqlEnum haskellSum = EnumMapper {     enumFromField :: RQ.FromField sqlEnum haskellSum@@ -97,7 +100,37 @@            -- ^ The @sqlEnum@ type variable is phantom. To protect            -- yourself against type mismatches you should set it to            -- the Haskell type that you use to represent the @ENUM@.-enumMapper type_ from to_ = EnumMapper {+enumMapper type_ = enumMapper' (render (doubleQuotes (text type_)))++enumMapperWithSchema :: String+           -- ^ The schema of the @ENUM@ type+           -> String+           -- ^ The name of the @ENUM@ type+           -> (String -> Maybe haskellSum)+           -- ^ A function which converts from the string+           -- representation of the ENUM field+           -> (haskellSum -> String)+           -- ^ A function which converts to the string representation+           -- of the ENUM field+           -> EnumMapper sqlEnum haskellSum+           -- ^ The @sqlEnum@ type variable is phantom. To protect+           -- yourself against type mismatches you should set it to+           -- the Haskell type that you use to represent the @ENUM@.+enumMapperWithSchema schema type_ = enumMapper' (render (doubleQuotes (text schema) <> text "." <> doubleQuotes (text type_)))++enumMapper' :: String+           -- ^ The name of the @ENUM@ type+           -> (String -> Maybe haskellSum)+           -- ^ A function which converts from the string+           -- representation of the ENUM field+           -> (haskellSum -> String)+           -- ^ A function which converts to the string representation+           -- of the ENUM field+           -> EnumMapper sqlEnum haskellSum+           -- ^ The @sqlEnum@ type variable is phantom. To protect+           -- yourself against type mismatches you should set it to+           -- the Haskell type that you use to represent the @ENUM@.+enumMapper' type_ from to_ = EnumMapper {     enumFromField = fromFieldEnum   , enumToFields = toFieldsEnum   }
src/Opaleye/Internal/Constant.hs view
@@ -14,7 +14,7 @@ import qualified Data.ByteString                 as SBS import qualified Data.ByteString.Lazy            as LBS import qualified Data.Scientific                 as Sci-import qualified Data.Time                       as Time+import qualified Data.Time.Compat                as Time import qualified Data.UUID                       as UUID  import qualified Data.Profunctor.Product         as PP@@ -103,6 +103,9 @@  instance D.Default ToFields Time.TimeOfDay (Column T.SqlTime) where   def = toToFields T.sqlTimeOfDay++instance D.Default ToFields Time.CalendarDiffTime (Column T.SqlInterval) where+  def = toToFields T.sqlInterval  instance D.Default ToFields (CI.CI ST.Text) (Column T.SqlCitext) where   def = toToFields T.sqlCiStrictText
src/Opaleye/Internal/Inferrable.hs view
@@ -21,7 +21,7 @@ import qualified Data.Scientific                 as Sci import qualified Data.Text.Lazy as LT import qualified Data.Text as ST-import qualified Data.Time as Time+import qualified Data.Time.Compat as Time import           Data.Typeable (Typeable) import           Data.UUID (UUID) import qualified Database.PostgreSQL.Simple.Range as R@@ -98,6 +98,10 @@   => D.Default (Inferrable FromField) T.SqlTime timeofday where   def = Inferrable D.def +instance calendardifftime ~ Time.CalendarDiffTime+  => D.Default (Inferrable FromField) T.SqlInterval calendardifftime where+  def = Inferrable D.def+ instance cttext ~ CI.CI ST.Text   => D.Default (Inferrable FromField) T.SqlCitext cttext where   def = Inferrable D.def@@ -204,6 +208,10 @@  instance C.Column T.SqlTime ~ cSqlTime   => D.Default (Inferrable ToFields) Time.TimeOfDay cSqlTime where+  def = Inferrable D.def++instance C.Column T.SqlInterval ~ cSqlInterval+  => D.Default (Inferrable ToFields) Time.CalendarDiffTime cSqlInterval where   def = Inferrable D.def  instance C.Column T.SqlCitext ~ cSqlCitext
src/Opaleye/Internal/PGTypes.hs view
@@ -13,7 +13,7 @@ import qualified Data.Text.Lazy.Encoding as LTextEncoding import qualified Data.ByteString as SByteString import qualified Data.ByteString.Lazy as LByteString-import qualified Data.Time as Time+import qualified Data.Time.Compat as Time import qualified Data.Time.Locale.Compat as Locale  unsafePgFormatTime :: Time.FormatTime t => HPQ.Name -> String -> t -> Column c
src/Opaleye/Internal/PGTypesExternal.hs view
@@ -20,7 +20,8 @@ import qualified Data.ByteString as SByteString import qualified Data.ByteString.Lazy as LByteString import           Data.Scientific as Sci-import qualified Data.Time as Time+import qualified Data.Time.Compat as Time+import qualified Data.Time.Format.ISO8601.Compat as Time.Format.ISO8601 import qualified Data.UUID as UUID  import           Data.Int (Int64)@@ -106,6 +107,10 @@ -- "We recommend not using the type time with time zone" -- http://www.postgresql.org/docs/8.3/static/datatype-datetime.html +sqlInterval :: Time.CalendarDiffTime -> Column PGInterval+sqlInterval = IPT.castToType "interval" . quote . Time.Format.ISO8601.iso8601Show+    where+      quote s = "'" ++ s ++ "'"  pgCiStrictText :: CI.CI SText.Text -> Column PGCitext pgCiStrictText = IPT.literalColumn . HPQ.StringLit . SText.unpack . CI.original@@ -179,6 +184,8 @@   showSqlType _ = "integer" instance IsSqlType SqlInt2 where   showSqlType _ = "smallint"+instance IsSqlType SqlInterval where+  showSqlType _ = "interval" instance IsSqlType SqlNumeric where   showSqlType _ = "numeric" instance IsSqlType SqlText where@@ -234,6 +241,12 @@ data SqlInt8 data SqlInt4 data SqlInt2+-- | Requires you to configure @intervalstyle@ as @iso_8601@.+--+-- You can configure @intervalstyle@ on every connection with a @SET@ command,+-- but for better performance you may want to configure it permanently in the+-- file found with @SHOW config_file;@.+data SqlInterval data SqlNumeric data SqlText data SqlTime@@ -264,6 +277,7 @@ type PGInt8 = SqlInt8 type PGInt4 = SqlInt4 type PGInt2 = SqlInt2+type PGInterval = SqlInterval type PGNumeric = SqlNumeric type PGText = SqlText type PGTime = SqlTime
src/Opaleye/Internal/RunQuery.hs view
@@ -39,7 +39,7 @@ import qualified Data.Text.Lazy.Encoding as LTE import qualified Data.ByteString as SBS import qualified Data.ByteString.Lazy as LBS-import qualified Data.Time as Time+import qualified Data.Time.Compat as Time import qualified Data.Scientific as Sci import qualified Data.String as String import           Data.UUID (UUID)@@ -242,6 +242,9 @@   defaultFromField = fromPGSFromField  instance DefaultFromField T.SqlTimestamptz Time.ZonedTime where+  defaultFromField = fromPGSFromField++instance DefaultFromField T.SqlInterval Time.CalendarDiffTime where   defaultFromField = fromPGSFromField  instance DefaultFromField T.SqlTime Time.TimeOfDay where
src/Opaleye/Operators.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-}  -- We can probably disable ConstraintKinds and TypeSynonymInstances -- when we move to Sql... instead of PG..@@ -100,6 +102,9 @@   , timestamptzAtTimeZone   , dateOfTimestamp   , now+  , IntervalNum+  , addInterval+  , minusInterval   -- * Deprecated   , exists   , notExists@@ -468,6 +473,27 @@  dateOfTimestamp :: F.Field T.SqlTimestamp -> F.Field T.SqlDate dateOfTimestamp (Column e) = Column (HPQ.FunExpr "date" [e])++-- | @IntervalNum from to@ determines from which date or time types an interval+-- can be added ('addInterval') or subtracted ('minusInterval`) and which is the+-- resulting type.+--+-- The instances should correspond to the interval + and - operations listed in:+--+-- https://www.postgresql.org/docs/current/functions-datetime.html#OPERATORS-DATETIME-TABLE+class IntervalNum from to | from -> to++instance IntervalNum T.SqlDate        T.SqlTimestamp+instance IntervalNum T.SqlInterval    T.SqlInterval+instance IntervalNum T.SqlTimestamp   T.SqlTimestamp+instance IntervalNum T.SqlTimestamptz T.SqlTimestamptz+instance IntervalNum T.SqlTime        T.SqlTime++addInterval :: IntervalNum from to => F.Field from -> F.Field T.SqlInterval -> F.Field to+addInterval = C.binOp (HPQ.:+)++minusInterval :: IntervalNum from to => F.Field from -> F.Field T.SqlInterval -> F.Field to+minusInterval = C.binOp (HPQ.:-)  {-# DEPRECATED exists "Identical to 'restrictExists'.  Will be removed in version 0.8." #-} exists :: QueryArr a b -> QueryArr a ()
src/Opaleye/SqlTypes.hs view
@@ -23,11 +23,13 @@   sqlLocalTime,   sqlZonedTime,   sqlTimeOfDay,+  P.sqlInterval,   -- ** Types   SqlDate,   SqlTime,   SqlTimestamp,   SqlTimestamptz,+  SqlInterval,   -- * JSON   -- ** Creating values   sqlJSON,@@ -96,6 +98,7 @@                                                    SqlTime,                                                    SqlTimestamp,                                                    SqlTimestamptz,+                                                   SqlInterval,                                                    SqlUuid,                                                    SqlCitext,                                                    SqlArray,@@ -112,7 +115,7 @@ import           Data.Scientific as Sci import qualified Data.Text as SText import qualified Data.Text.Lazy as LText-import qualified Data.Time as Time+import qualified Data.Time.Compat as Time import qualified Data.UUID as UUID  import qualified Database.PostgreSQL.Simple.Range as R@@ -169,7 +172,6 @@  -- "We recommend not using the type time with time zone" -- http://www.postgresql.org/docs/8.3/static/datatype-datetime.html-  sqlCiStrictText :: CI.CI SText.Text -> F.Field SqlCitext sqlCiStrictText = P.pgCiStrictText