haskell postgresql-простой несовместимый тип _int8 и Int64 (и Integer)
Приведенная ниже ошибочная функция является частью программы под названием subdivide, которая работает с геопространственными пересечениями Postgis на стороне сервера и обрабатывает возвращенный массив Int64 на стороне клиента.
Он построен и работает в режиме Stack с разрешением Nightly 2016-08-02 и явным указанием архитектуры x86_64.
Я получаю следующую ошибку времени выполнения при выполнении запроса Postgres, определенного как "intersectionsSql" (см. Комментарий "RUNTIME ERROR HERE"):
"Created table: server : [Only {fromOnly = \"PostgreSQL 9.6beta2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit\"}] quadrant: BOX3D(-180.0 90.0, -90.0 45.0)"
subdivide: Incompatible {errSQLType = "_int8", errSQLTableOid = Nothing, errSQLField = "object_ids", errHaskellType = "Int64", errMessage = "types incompatible"}
Я пробовал Integer, Int64 и Int, все с одинаковым результатом, что нелогично, так как все типы Haskell должны быть совместимы с _int8 в соответствии с документацией простого экземпляра PostgreSQL:
Запрос SQL должен возвращать одну строку postgres bigint[], которую я подтвердил через PGAdmin.
Есть идеи?
Также любые комментарии о том, как я написал код - прошло более десяти лет с тех пор, как я работал с GHC в прошлый раз, и времена изменились.
Спасибо за внимание.
Майк Томас
accumulateIntersections :: Identifier -> Identifier -> ConnectInfo -> ((Double,Double),(Double,Double)) -> IO ()
accumulateIntersections sourceTable accumulationTable connectionInfo q =
let
theBox = makeBox3D (fst (fst q)) (snd (fst q)) (fst (snd q)) (snd (snd q))
theValue = (Only theBox)
dropTable = [sql| DROP TABLE IF EXISTS ? CASCADE |]
createTable = [sql| CREATE TABLE ? ( quadrant_id BIGSERIAL, area_metres_squared FLOAT8, shape GEOMETRY, object_ids BIGINT[] ) |]
aggregateSql = [sql| DROP AGGREGATE IF EXISTS _array_agg (anyarray);
CREATE AGGREGATE _array_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray);
|]
intersectionsSql = [sql| SELECT _array_agg (object_ids) object_ids
FROM ?
WHERE ST_Intersects(ST_SetSRID ( ?::box3d, 4326 ), shape)
|]
insertIntersections = [sql| INSERT INTO ? (shape, object_ids)
VALUES ( ST_SetSRID ( ?::box3d, 4326 )
, ? ) |]
in
do
connection <- connect connectionInfo
execute_ connection aggregateSql
postgresVersion <- (query_ connection "SELECT version()" :: IO [Only String])
i0 <- execute connection dropTable (Only accumulationTable)
i1 <- execute connection createTable (Only accumulationTable)
print ("Created table: server : " ++ (show postgresVersion) ++ " quadrant: " ++ theBox)
is :: [Only Int64] <- query connection intersectionsSql (sourceTable, theBox) -- RUNTIME ERROR HERE
print ("Intersections done.")
ids::[Int64] <- forM is (\(Only id) -> return id)
print ("Ids done.")
close connection
return ()
1 ответ
См. Приведенный выше комментарий, переданный Л.П. Смитом, с которым я связался, когда здесь не было ответов. Это решает мою проблему.
Ключ должен был признать, что _int8 представляет массив из 8-байтовых целых, а не думать, как я это сделал, что это было внутреннее представление для одного 8-байтового целого числа. Леон предложил изменить вместо "[Only (Vector Int64)]" вместо "[Only Int64]" в строке, отмеченной выше как точку ошибки времени выполнения.
Спасибо Леон.