Postgres-simple的FromRow实例定义错误

时间:2019-04-03 13:15:42

标签: postgresql haskell aeson

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。累积收入给出了以下异常。您可以忽略spock部分。

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

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

1 个答案:

答案 0 :(得分: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值相对应的字段。