fix: add interval support

This commit is contained in:
2024-06-14 16:09:59 -05:00
parent b4a84a3210
commit fbb1f3b8a5
9 changed files with 289 additions and 9 deletions

View File

@@ -0,0 +1,37 @@
module Test.Data.Postgres.Interval where
import Prelude
import Data.Postgres.Interval as Interval
import Data.Time.Duration (Milliseconds(..))
import Data.Traversable (for_)
import Data.Tuple.Nested (type (/\), (/\))
import Effect.Class (liftEffect)
import Test.Spec (Spec, describe, it)
import Test.Spec.Assertions (shouldEqual)
spec :: Spec Unit
spec =
describe "Data.Postgres.Interval" do
it "parse & toRecord" do
p <- liftEffect $ Interval.parse "3 days 04:05:06"
Interval.toRecord p `shouldEqual` Interval.zero {days = 3, hours = 4, minutes = 5, seconds = 6}
it "make & toRecord" do
let p = Interval.make $ Interval.zero {days = 3, hours = 4, minutes = 5, seconds = 6}
Interval.toRecord p `shouldEqual` Interval.zero {days = 3, hours = 4, minutes = 5, seconds = 6}
describe "fromDuration" do
for_
[ Milliseconds 100.0 /\ Interval.zero {milliseconds = 100.0}
, Milliseconds 1000.0 /\ Interval.zero {seconds = 1}
, Milliseconds 1100.0 /\ Interval.zero {seconds = 1, milliseconds = 100.0}
, Milliseconds 60000.0 /\ Interval.zero {minutes = 1}
, Milliseconds 61100.0 /\ Interval.zero {minutes = 1, seconds = 1, milliseconds = 100.0}
, Milliseconds 3600000.0 /\ Interval.zero {hours = 1}
, Milliseconds 3661100.0 /\ Interval.zero {hours = 1, minutes = 1, seconds = 1, milliseconds = 100.0}
, Milliseconds 86400000.0 /\ Interval.zero {days = 1}
, Milliseconds 90061100.0 /\ Interval.zero {days = 1, hours = 1, minutes = 1, seconds = 1, milliseconds = 100.0}
]
\(i /\ o) -> it ("converts " <> show i) do
Interval.toRecord (Interval.fromDuration i) `shouldEqual` o

View File

@@ -2,28 +2,28 @@ module Test.Data.Postgres where
import Prelude
import Control.Monad.Gen (chooseInt, elements, oneOf)
import Control.Monad.Gen (chooseFloat, chooseInt, elements, oneOf)
import Control.Parallel (parTraverse_)
import Data.Array (intercalate)
import Data.Array as Array
import Data.Array.NonEmpty as Array.NonEmpty
import Data.DateTime (DateTime(..), canonicalDate)
import Data.DateTime.Instant as Instant
import Data.Enum (toEnum)
import Data.Foldable (fold)
import Data.Identity (Identity)
import Data.Int as Int
import Data.Maybe (Maybe(..), fromJust, maybe)
import Data.Maybe (Maybe(..), fromJust, fromMaybe)
import Data.Newtype (class Newtype, unwrap, wrap)
import Data.Number (abs) as Number
import Data.Postgres (class Rep)
import Data.Postgres.Interval (Interval)
import Data.Postgres.Interval as Interval
import Data.Postgres.Query.Builder as Q
import Data.Postgres.Raw (Raw, jsNull)
import Data.Postgres.Raw as Raw
import Data.Postgres.Result (class FromRow)
import Data.RFC3339String as DateTime.ISO
import Data.String as String
import Data.Time (Time(..))
import Data.Time.Duration (class Duration, Days, Hours, Milliseconds, Minutes, Seconds)
import Data.Traversable (for, sequence)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
@@ -35,20 +35,45 @@ import Effect.Unsafe (unsafePerformEffect)
import Foreign (Foreign, unsafeToForeign)
import Foreign.Object as Object
import JS.BigInt (BigInt)
import JS.BigInt as BigInt
import Node.Buffer (Buffer)
import Node.Buffer as Buffer
import Partial.Unsafe (unsafePartial)
import Simple.JSON (writeJSON)
import Test.Common (withClient, withPoolClient)
import Test.Common (withPoolClient)
import Test.QuickCheck (class Arbitrary, arbitrary, randomSeed)
import Test.QuickCheck.Gen (sample, vectorOf)
import Test.Spec (Spec, SpecT, around, describe, it, parallel)
import Test.Spec (Spec, SpecT, around, describe, it)
import Test.Spec.Assertions (fail)
foreign import readBigInt64BE :: Buffer -> Effect BigInt
foreign import dbg :: forall a. a -> Effect Unit
newtype GenIntervalSubMonth = GenIntervalSubMonth Interval
derive instance Newtype GenIntervalSubMonth _
instance Arbitrary GenIntervalSubMonth where
arbitrary = do
days <- chooseInt 0 30
hours <- chooseInt 0 23
minutes <- chooseInt 0 59
seconds <- chooseInt 0 59
milliseconds <- chooseFloat 0.0 999.9
pure $ wrap $ Interval.make $ Interval.zero {days = days, hours = hours, minutes = minutes, seconds = seconds, milliseconds = milliseconds}
newtype GenInterval = GenInterval Interval
derive instance Newtype GenInterval _
instance Arbitrary GenInterval where
arbitrary = do
years <- chooseInt 0 10
months <- chooseInt 0 11
days <- chooseInt 0 30
hours <- chooseInt 0 23
minutes <- chooseInt 0 59
seconds <- chooseInt 0 59
milliseconds <- chooseFloat 0.0 999.9
pure $ wrap $ Interval.make {years, months, days, hours, minutes, seconds, milliseconds}
newtype GenSmallInt = GenSmallInt Int
derive instance Newtype GenSmallInt _
@@ -196,6 +221,17 @@ spec =
around withPoolClient
$ describe "Data.Postgres"
$ do
let
durationFromGenInterval :: forall d. Semigroup d => Duration d => Newtype d Number => GenIntervalSubMonth -> d
durationFromGenInterval = fromMaybe (wrap 0.0) <<< Interval.toDuration <<< unwrap
durationEq :: forall d. Duration d => Newtype d Number => d -> d -> Boolean
durationEq a b = Number.abs (unwrap a - unwrap b) <= 0.001
check @Milliseconds @GenIntervalSubMonth { purs: "Milliseconds", sql: "interval", fromArb: durationFromGenInterval, isEq: durationEq}
check @Seconds @GenIntervalSubMonth { purs: "Seconds", sql: "interval", fromArb: durationFromGenInterval, isEq: durationEq}
check @Minutes @GenIntervalSubMonth { purs: "Minutes", sql: "interval", fromArb: durationFromGenInterval, isEq: durationEq}
check @Hours @GenIntervalSubMonth { purs: "Hours", sql: "interval", fromArb: durationFromGenInterval, isEq: durationEq}
check @Days @GenIntervalSubMonth { purs: "Days", sql: "interval", fromArb: durationFromGenInterval, isEq: durationEq}
check @Int @GenSmallInt { purs: "Int", sql: "int2", fromArb: unwrap, isEq: eq }
check @Int { purs: "Int", sql: "int4", fromArb: identity, isEq: eq }
check @String @GenString { purs: "String", sql: "text", fromArb: unwrap, isEq: eq }

View File

@@ -23,6 +23,7 @@ import Node.EventEmitter as Event
import Test.Control.Monad.Postgres as Test.Control.Monad.Postgres
import Test.Data.Postgres as Test.Data.Postgres
import Test.Data.Postgres.Custom as Test.Data.Postgres.Custom
import Test.Data.Postgres.Interval as Test.Data.Postgres.Interval
import Test.Effect.Postgres.Client as Test.Effect.Postgres.Client
import Test.Effect.Postgres.Pool as Test.Effect.Postgres.Pool
import Test.Spec.Reporter (specReporter)
@@ -65,6 +66,7 @@ main = launchAff_ do
$ runSpec [ specReporter ] do
Test.Data.Postgres.Custom.spec
Test.Data.Postgres.spec
Test.Data.Postgres.Interval.spec
Test.Effect.Postgres.Client.spec
Test.Effect.Postgres.Pool.spec
Test.Control.Monad.Postgres.spec