Skip to content

Commit ddae86b

Browse files
Refactor numeric tests
1 parent da8150e commit ddae86b

File tree

5 files changed

+47
-39
lines changed

5 files changed

+47
-39
lines changed

postgres-wire.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ test-suite postgres-wire-test
9999
, tasty-hunit
100100
, tasty-quickcheck
101101
, QuickCheck >= 2.9
102+
, scientific
103+
, time
104+
, uuid
102105
, tagged
103106
ghc-options: -threaded -rtsopts -with-rtsopts=-N
104107
default-language: Haskell2010

src/Database/PostgreSQL/Protocol/Codecs/Decoders.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Database.PostgreSQL.Protocol.Codecs.Numeric
2424
-- 2 bytes - count of columns in the DataRow
2525
{-# INLINE dataRowHeader #-}
2626
dataRowHeader :: Decode ()
27-
dataRowHeader = skipBytes 7
27+
dataRowHeader = skipBytes 7
2828

2929
{-# INLINE fieldLength #-}
3030
fieldLength :: Decode Int
@@ -73,13 +73,13 @@ arrayDimensions dims = V.reverse <$> V.replicateM dims arrayDimSize
7373
arrayFieldDecoder :: Int -> (V.Vector Int -> Decode a) -> FieldDecoder a
7474
arrayFieldDecoder dims f _ = arrayHeader *> arrayDimensions dims >>= f
7575

76-
-- | Decodes only a content of the field.
77-
type FieldDecoder a = Int -> Decode a
78-
7976
--
8077
-- Primitives
8178
--
8279

80+
-- | Decodes only a content of the field.
81+
type FieldDecoder a = Int -> Decode a
82+
8383
{-# INLINE bool #-}
8484
bool :: FieldDecoder Bool
8585
bool _ = (== 1) <$> getWord8
@@ -134,9 +134,9 @@ bsJsonBytes len = getWord8 *> getByteString (len - 1)
134134
numeric :: FieldDecoder Scientific
135135
numeric _ = do
136136
ndigits <- getWord16BE
137-
weight <- getInt16BE
138-
sign <- getWord16BE >>= fromNumericSign
139-
_ <- getWord16BE
137+
weight <- getInt16BE
138+
sign <- fromNumericSign =<< getWord16BE
139+
_ <- getWord16BE
140140
numericToScientific sign weight <$>
141141
replicateM (fromIntegral ndigits) getWord16BE
142142

src/Database/PostgreSQL/Protocol/Codecs/Encoders.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Database.PostgreSQL.Protocol.Store.Encode
1616
import Database.PostgreSQL.Protocol.Types
1717
import Database.PostgreSQL.Protocol.Codecs.Time
1818
import Database.PostgreSQL.Protocol.Codecs.Numeric
19+
1920
--
2021
-- Primitives
2122
--
@@ -59,7 +60,7 @@ int8 = putInt64BE
5960

6061
{-# INLINE interval #-}
6162
interval :: DiffTime -> Encode
62-
interval v = let (mcs, days, months) = diffTimeToInterval v
63+
interval v = let (mcs, days, months) = diffTimeToInterval v
6364
in putInt64BE mcs <> putInt32BE days <> putInt32BE months
6465

6566
-- | Encodes representation of JSON as @ByteString@.
Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
{-# language LambdaCase #-}
2-
module Database.PostgreSQL.Protocol.Codecs.Numeric where
3-
4-
-- TODO test it
5-
import Data.Tuple
6-
import Data.Word
7-
import Data.Int
8-
import Data.Foldable
9-
import Data.Scientific
10-
import Data.List (unfoldr)
112

12-
integerToDigits :: Integer -> [Word16]
13-
integerToDigits = (reverse.) . unfoldr $ \case
14-
0 -> Nothing
15-
n -> let (rest, rem) = n `divMod` nBase in Just (fromIntegral rem, rest)
3+
module Database.PostgreSQL.Protocol.Codecs.Numeric where
164

17-
toNumericSign :: Scientific -> Word16
18-
toNumericSign s | s >= 0 = 0x0000
19-
| otherwise = 0x4000
5+
import Data.Word (Word16)
6+
import Data.Int (Int16)
7+
import Data.Foldable (foldl')
8+
import Data.Scientific (Scientific, scientific, base10Exponent, coefficient)
9+
import Data.List (unfoldr)
2010

11+
{-# INLINE scientificToNumeric #-}
2112
scientificToNumeric :: Scientific -> (Int16, Word16, [Word16])
2213
scientificToNumeric number =
2314
let a = base10Exponent number `mod` nBaseDigits
@@ -28,24 +19,40 @@ scientificToNumeric number =
2819
scale = fromIntegral . negate $ min (base10Exponent number) 0
2920
in (weight, scale, digits)
3021

31-
digitsToInteger :: [Word16] -> Integer
32-
digitsToInteger = foldl' (\acc n -> acc * nBase + fromIntegral n) 0
22+
{-# INLINE numericToScientific #-}
23+
numericToScientific :: Integer -> Int16 -> [Word16] -> Scientific
24+
numericToScientific sign weight digits =
25+
let coef = digitsToInteger digits * sign
26+
exp' = (fromIntegral weight + 1 - length digits) * nBaseDigits
27+
in scientific coef exp'
3328

29+
{-# INLINE toNumericSign #-}
30+
toNumericSign :: Scientific -> Word16
31+
toNumericSign s | s >= 0 = 0x0000
32+
| otherwise = 0x4000
33+
34+
{-# INLINE fromNumericSign #-}
3435
fromNumericSign :: (Monad m, Num a) => Word16 -> m a
3536
fromNumericSign 0x0000 = pure 1
3637
fromNumericSign 0x4000 = pure $ -1
3738
-- NaN code is 0xC000, it is not supported.
3839
fromNumericSign _ = fail "Unknown numeric sign"
3940

40-
numericToScientific :: Integer -> Int16 -> [Word16] -> Scientific
41-
numericToScientific sign weight digits =
42-
let coef = digitsToInteger digits * sign
43-
exp' = (fromIntegral weight + 1 - length digits) * nBaseDigits
44-
in scientific coef exp'
41+
{-# INLINE integerToDigits #-}
42+
integerToDigits :: Integer -> [Word16]
43+
integerToDigits = (reverse.) . unfoldr $ \case
44+
0 -> Nothing
45+
n -> let (rest, rem) = n `divMod` nBase in Just (fromIntegral rem, rest)
46+
47+
{-# INLINE digitsToInteger #-}
48+
digitsToInteger :: [Word16] -> Integer
49+
digitsToInteger = foldl' (\acc n -> acc * nBase + fromIntegral n) 0
4550

51+
{-# INLINE nBase #-}
4652
nBase :: Num a => a
4753
nBase = 10000
4854

55+
{-# INLINE nBaseDigits #-}
4956
nBaseDigits :: Num a => a
5057
nBaseDigits = 4
5158

tests/Codecs/QuickCheck.hs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ makeCodecEncodeProperty c oid queryString encoder fPrint v = monadicIO $ do
6565
sendBatchAndSync c [q]
6666
dr <- readNextData c
6767
waitReadyForQuery c
68-
r <- either (error . show) (pure . BC.unpack . decodeOneRow decoder) dr
69-
-- print $ fPrint v <> " " <> r
70-
pure r
68+
either (error . show) (pure . BC.unpack . decodeOneRow decoder) dr
7169

7270
assertQCEqual (fPrint v) r
7371

@@ -96,7 +94,7 @@ mkCodecEncodeTest name oids queryString encoder fPrint =
9694

9795
testCodecsEncodeDecode :: TestTree
9896
testCodecsEncodeDecode = testGroup "Codecs property 'encode . decode = id'"
99-
[ {-mkCodecTest "bool" PGT.bool PE.bool PD.bool
97+
[ mkCodecTest "bool" PGT.bool PE.bool PD.bool
10098
, mkCodecTest "bytea" PGT.bytea PE.bytea PD.bytea
10199
, mkCodecTest "char" PGT.char PE.char PD.char
102100
, mkCodecTest "date" PGT.date PE.date PD.date
@@ -110,12 +108,11 @@ testCodecsEncodeDecode = testGroup "Codecs property 'encode . decode = id'"
110108
(fmap JsonString <$> PD.bsJsonText)
111109
, mkCodecTest "jsonb" PGT.jsonb (PE.bsJsonBytes .unJsonString)
112110
(fmap JsonString <$> PD.bsJsonBytes)
113-
-- TODO
114-
, -}mkCodecTest "numeric" PGT.numeric PE.numeric PD.numeric
115-
{-, mkCodecTest "text" PGT.text PE.bsText PD.bsText
111+
, mkCodecTest "numeric" PGT.numeric PE.numeric PD.numeric
112+
, mkCodecTest "text" PGT.text PE.bsText PD.bsText
116113
, mkCodecTest "timestamp" PGT.timestamp PE.timestamp PD.timestamp
117114
, mkCodecTest "timestamptz" PGT.timestamptz PE.timestamptz PD.timestamptz
118-
, mkCodecTest "uuid" PGT.uuid PE.uuid PD.uuid-}
115+
, mkCodecTest "uuid" PGT.uuid PE.uuid PD.uuid
119116
]
120117

121118
testCodecsEncodePrint :: TestTree

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy