下面的错误函数是一个名为subdive的程序的一部分,该程序在服务器端使用Postgis地理空间交集,并在客户端处理返回的Int64数组。
它是在Stack下构建和运行的,解析为Nightly 2016-08-02,并明确指定体系结构x86_64。
我在执行定义为"intersectionsSql"的Postgres查询时遇到以下运行时错误(请参阅此处的runtime error注释):
"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,结果都是一样的,这是违反直觉的,因为根据PostgreSQL的简单实例文档:,那些Haskell类型应该都与_int8兼容
https://hackage.haskell.org/package/postgresql-simple-0.5.0.0/candidate/docs/Database-PostgreSQL-Simple-FromField.html
SQL查询应该返回一行postgres bigint[],我已经通过PGAdmin确认了这一点。
有什么想法吗?
此外,关于我如何编写代码的任何评论——自上次我与GHC合作以来,已经有十多年了,时代已经改变了。
谢谢你的考虑。
Mike Thomas
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 ()
请参阅LP Smith转发的上述评论,当这里没有答案时,我联系了他。它解决了我的问题。
关键是要认识到_int8表示一个8字节整数的数组,而不是像我所做的那样,认为它是单个8字节整型的内部表示。Leon建议的更改是用"[Only(Vector Int64)]"代替上面标记的作为运行时错误点的行中的"[Onley Int64]"。
谢谢你,里昂。