postgresql-simple-interval 1.0.0.0 → 1.0.1.0
raw patch · 3 files changed
+39/−7 lines, 3 filesdep +template-haskell
Dependencies added: template-haskell
Files
- postgresql-simple-interval.cabal +2/−1
- source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs +11/−5
- source/test-suite/Main.hs +26/−1
postgresql-simple-interval.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: postgresql-simple-interval-version: 1.0.0.0+version: 1.0.1.0 synopsis: A simple interval type for PostgreSQL. description: This library provides a simple interval type for PostgreSQL. It supports@@ -64,6 +64,7 @@ build-depends: persistent ^>=2.17, scientific ^>=0.3.8,+ template-haskell >=2.15 && <2.24, text >=1.2.4 && <1.3 || >=2.0 && <2.2, -- cabal-gild: discover source/library
source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveLift #-} {-# LANGUAGE NumDecimals #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -27,6 +28,7 @@ import qualified Database.PostgreSQL.Simple.ToField as Postgres import qualified Database.PostgreSQL.Simple.TypeInfo.Static as Postgres import qualified GHC.TypeLits as TypeLits+import qualified Language.Haskell.TH.Syntax as TH -- | This type represents a PostgreSQL interval. Intervals can have month, day, -- and microsecond components. Each component is bounded, so they are not@@ -53,7 +55,7 @@ days :: !Int.Int32, microseconds :: !Int.Int64 }- deriving (Eq, Show)+ deriving (Eq, TH.Lift, Show) -- | Uses 'parse'. Ensures that the OID is 'Postgres.intervalOid'. instance Postgres.FromField Interval where@@ -581,9 +583,7 @@ <> " us" -- | Parses an interval. This is not a general purpose parser. It only supports--- the formats that PostgreSQL generates. For example, it will fail to parse an--- interval like @"1 week"@ because PostgreSQL never uses weeks when rendering--- intervals.+-- the formats that PostgreSQL generates. parse :: A.Parser Interval parse = -- Start with parsers that have non-empty prefixes, in order to avoid@@ -602,10 +602,11 @@ parseInfinities :: A.Parser Interval parseInfinities =- -- Both `-infinity` and `infinity` are new as of PostgreSQL 17.0.+ -- `infinity` is new as of PostgreSQL 17.0. -- https://www.postgresql.org/message-id/E1r2rB1-005PHm-UL%40gemulon.postgresql.org A.choice [ MkInterval minBound minBound minBound <$ "-infinity",+ MkInterval maxBound maxBound maxBound <$ "+infinity", MkInterval maxBound maxBound maxBound <$ "infinity" ] @@ -636,6 +637,7 @@ flip A.sepBy " " $ A.choice [ Years <$> A.signed A.decimal <* maybePlural " year",+ Weeks <$> A.signed A.decimal <* maybePlural " week", Months <$> A.signed A.decimal <* maybePlural " mon", Days <$> A.signed A.decimal <* maybePlural " day", Hours <$> A.signed A.decimal <* maybePlural " hour",@@ -652,6 +654,7 @@ flip A.sepBy " " $ A.choice [ Years <$> A.signed A.decimal <* maybePlural " year",+ Weeks <$> A.signed A.decimal <* maybePlural " week", Months <$> A.signed A.decimal <* maybePlural " mon", Days <$> A.signed A.decimal <* maybePlural " day" ]@@ -688,6 +691,7 @@ -- are accepted, like years and months. data Component = Years !Integer+ | Weeks !Integer | Months !Integer | Days !Integer | Hours !Integer@@ -701,6 +705,7 @@ fromComponent :: Component -> Maybe Interval fromComponent c = case c of Years y -> fromYears =<< Bits.toIntegralSized y+ Weeks w -> fromWeeks =<< Bits.toIntegralSized w Months m -> fromMonths <$> Bits.toIntegralSized m Days d -> fromDays <$> Bits.toIntegralSized d Hours h -> fromHours =<< Bits.toIntegralSized h@@ -722,6 +727,7 @@ negateComponent :: Component -> Component negateComponent c = case c of Years y -> Years (-y)+ Weeks w -> Weeks (-w) Months m -> Months (-m) Days d -> Days (-d) Hours h -> Hours (-h)
source/test-suite/Main.hs view
@@ -394,13 +394,38 @@ let actual = Attoparsec.parseOnly I.parse "invalid" actual `H.shouldBe` Left "Failed reading: empty" - H.it "succeeds with positive infinity" $ do+ H.it "succeeds with implicit positive infinity" $ do let actual = Attoparsec.parseOnly I.parse "infinity" actual `H.shouldBe` Right (I.MkInterval maxBound maxBound maxBound) + H.it "succeeds with explicit positive infinity" $ do+ let actual = Attoparsec.parseOnly I.parse "+infinity"+ actual `H.shouldBe` Right (I.MkInterval maxBound maxBound maxBound)+ H.it "succeeds with negative infinity" $ do let actual = Attoparsec.parseOnly I.parse "-infinity" actual `H.shouldBe` Right (I.MkInterval minBound minBound minBound)++ H.describe "weeks" $ do+ H.it "succeeds with zero" $ do+ let actual = Attoparsec.parseOnly I.parse "0 weeks"+ actual `H.shouldBe` Right (I.MkInterval 0 0 0)++ H.it "succeeds with implicit positive" $ do+ let actual = Attoparsec.parseOnly I.parse "1 week"+ actual `H.shouldBe` Right (I.MkInterval 0 7 0)++ H.it "succeeds with explicit positive" $ do+ let actual = Attoparsec.parseOnly I.parse "+2 weeks"+ actual `H.shouldBe` Right (I.MkInterval 0 14 0)++ H.it "succeeds with negative" $ do+ let actual = Attoparsec.parseOnly I.parse "-3 weeks"+ actual `H.shouldBe` Right (I.MkInterval 0 (-21) 0)++ H.it "succeeds with verbose" $ do+ let actual = Attoparsec.parseOnly I.parse "@ 4 weeks"+ actual `H.shouldBe` Right (I.MkInterval 0 28 0) Monad.forM_ intervalStyles $ \(_, field) -> Monad.forM_ examples $ \example -> do