Ошибка совместимости типа count(*) с Database.PostgreSQL.Simple?
Ошибка
*** Exception: Incompatible {errSQLType = "int8", errHaskellType = "Int", errMessage = "types incompatible"}
Похоже, любое значение, возвращаемое count(*)
в запросе должны быть преобразованы в Integer
скорее, чем Int
, Если я изменю эти конкретные переменные на тип Integer, запросы будут работать.
Но эта ошибка не возникала на другой машине с таким же точным кодом. Первая машина была 32-битной, а другая - 64-битной. Это единственное отличие, которое я мог различить.
У кого-нибудь есть понимание того, что происходит?
2 ответа
Функции count () в PostgreSQL возвращают тип Bigint, см.
http://www.postgresql.org/docs/9.2/static/functions-aggregate.html
Bigint составляет 8 байт, см. http://www.postgresql.org/docs/9.2/static/datatype-numeric.html
Haskell int равен ~ 2**29, что подразумевает 4-байтовое целое число.
http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Int.html
Тогда это нормально, что PostgreSQL или его API не будут выполнять неявное преобразование с понижением точности.
Так что используйте тип Haskell int64 или число приведения (*) к целому числу.
Как описано в модуле FromField, postgresql-simple будет выполнять преобразование на стороне клиента между числовыми типами, только когда нет никакой возможности переполнения или потери точности. Обратите особое внимание на список типов в пикшах для instance FromField Int
: "int2, int4, и если скомпилировано как 64-битный код, так и int8. Эта библиотека была скомпилирована как 32-битный код." Последняя часть этого комментария, конечно, специфична для сборки, которую выполняет сам хакер.
На 32-битных платформах, Int
является 32-разрядным целым числом, и на 64-разрядных платформах, Int
является 64-битным целым числом Если вы используете Int32
вы получите то же исключение. Ты можешь использовать Int64
или произвольная точность Integer
типа, чтобы избежать этой проблемы на обоих видах платформ.