使用postgres-simple的FromRow实例定义出错

问题描述 投票:0回答:1
data CumulativeRevenue = CumulativeRevenue
  { payment_date :: T.Text
  , amount       :: Double
  , sum          :: Double
  } deriving (Show, Generic, Aeson.ToJSON, Aeson.FromJSON)

instance Postgres.FromRow CumulativeRevenue where
  fromRow = CumulativeRevenue
            <$> Postgres.field
            <*> Postgres.field
            <*> Postgres.field

cumulativeRevenue :: Postgres.Connection -> IO [CumulativeRevenue]
cumulativeRevenue conn = Postgres.query_ conn
  "SELECT payment_date, amount, sum(amount) OVER (ORDER by payment_date) \
  \ FROM (\
  \ SELECT CAST (payment_date as TEXT) AS payment_date, SUM(amount) AS \
  \ amount \
  \ FROM payment \
  \ GROUP BY CAST(payment_date AS TEXT) \
  \ ) p \
  \ ORDER BY payment_date \
  \"

目前,我有上面的代码。完整的代码是here。 cumulativeRevenue提供如下例外。你可以忽略spock部分。

Spock Error while handling ["cumulative"]: Incompatible {errSQLType = "numeric", errSQLTableOid = Nothing, errSQLField = "amount", errHaskellType = "Double", errMessage = "types incompatible"}

我不清楚在CumulativeRevenue中为amount和sum字段指定什么。有人可以帮助我吗?在使用postgres-simple库时,有没有更简单的方法来计算从Haskell类型到SQL类型的转换类型,反之亦然?

postgresql haskell aeson
1个回答
0
投票

FromField有一个Double实例,但它不适用于numeric,因为numeric是可变精度as per the PostgresSQL documentation。如果你看看postgresql-simple documentation,你会发现Ratio Integer(又名Rational)实例确实支持numeric

所以你在这里可以做的是两件事之一:

  1. 使用Rational而不是Double为你的amount字段
  2. 决定你没有精确度(尽管为什么你在SQL端使用numeric呢?),并做类似的事情
import Data.Ratio

loseNumericPrecision :: Postgres.RowParser Double
loseNumericPrecision = fmap fromRational Postgres.field

并使用它而不是Postgres.field为您的字段对应numeric值。

© www.soinside.com 2019 - 2024. All rights reserved.