1

以下の誤った関数は、サーバー側で Postgis 地理空間交差を処理し、クライアント側で返された Int64 の配列を処理する subdivide と呼ばれるプログラムの一部です。

Stack でビルドおよび実行され、Nightly 2016-08-02 に解決され、アーキテクチャ x86_64 が明示的に指定されます。

「intersectionsSql」として定義された Postgres クエリを実行すると、次のランタイム エラーが発生します (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 と互換性があるはずなので、直観に反します。

https://hackage.haskell.org/package/postgresql-simple-0.5.0.0/candidate/docs/Database-PostgreSQL-Simple-FromField.html

SQL クエリは、postgres bigint[] の単一行を返す必要があります。これは、PGAdmin で確認しました。

何か案は?

また、私がどのようにコードを書いたかについてのコメントもあります - 最後に GHC を使ってから 10 年以上経ち、時代が変わりました。

ご検討いただきありがとうございます。

マイク・トーマス

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 ()
4

1 に答える 1

0

ここで回答が得られなかったときに私が連絡を取った LP Smith から中継された上記のコメントを参照してください。それは私の問題を解決します。

重要なのは、_int8 が単一の 8 バイト整数の内部表現であると考えたのではなく、_int8 が 8 バイト整数の配列を表していることを認識することでした。レオンの提案した変更は、実行時エラーのポイントとして上記でマークされた行の「[Only (Vector Int64)]」を「[Only (Vector Int64)]」に置き換えることでした。

ありがとうレオン。

于 2016-08-05T00:01:37.283 に答える