Ошибка определения экземпляра FromRow с помощью postgres-simple - PullRequest
0 голосов
/ 03 апреля 2019
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 \
  \"

В настоящее время у меня есть фрагмент кода выше. Полный код здесь . CumulativeRevenue дает исключение, как показано ниже. Вы можете игнорировать часть спока.

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

Мне не ясно, что указывать для полей суммы и суммы в CumulativeRevenue. Может ли кто-нибудь помочь мне с этим? Есть ли какой-нибудь более простой способ выяснить преобразования типов из типов Haskell в типы SQL или наоборот при использовании библиотеки postgres-simple?

1 Ответ

0 голосов
/ 03 апреля 2019

Существует экземпляр FromField для Double, но он не работает с numeric, потому что numeric имеет переменную точность согласно документации PostgresSQL . Если вы посмотрите документацию postgresql-simple , вы увидите, что экземпляр Ratio Integer (он же Rational) поддерживает numeric.

Итак, что вы можете сделать здесь, это одна из двух вещей:

  1. Используйте Rational вместо Double для своего amount поля
  2. Решите, что вы в порядке с потерей точности (хотя почему вы тогда используете numeric на стороне SQL?), И сделайте что-то вроде
import Data.Ratio

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

и используйте это вместо Postgres.field для ваших полей, соответствующих numeric значениям.

...