多くの手順の 1 つとして、生のバイナリ BLOB データをデータベースに保存および取得する必要がある Haskell アプリケーションがあります。代わりに、そのデータをプレーンディスクファイルに保存することを完全に決定しているわけではありませんが、それにより、追加のアクセス許可の問題が発生し始めるので、今はデータベースを使用したいと考えています.
type の列を持つテーブルを作成しましたbytea
。
メモリに遅延バイト文字列があります。
こんな風に電話したら
run conn "INSERT INTO documents VALUES (?)" [toSql $ rawData mydoc]
postgres はデータに少し腹を立てます。正確なエラーメッセージは
invalid byte sequence for encoding \"UTF8\": 0xcf72
また、データ ストリームに NUL 値があることも間違いなくわかっています。では、これらすべてを念頭に置いて、挿入のためにデータを安全にエンコードする正しい方法は何でしょうか?
更新しました
これが私のテーブルの説明です
db=> \d+ documents
Table "public.documents"
Column | Type | Modifiers | Storage | Description
-----------------+-----------------------------+-----------+----------+-------------
id | character varying(16) | not null | extended |
importtime | timestamp without time zone | not null | plain |
filename | character varying(255) | not null | extended |
data | bytea | not null | extended |
recordcount | integer | not null | plain |
parsesuccessful | boolean | not null | plain |
Indexes:
"documents_pkey" PRIMARY KEY, btree (id)
これは、jamsdidh のコードを追加した後に私が抱えている現在の問題を示すモジュールの全文です。私のエラーメッセージは、上記のエンコーディングの問題から「バイトタイプの入力構文が無効です」に変わりました。
module DBMTest where
import qualified Data.Time.Clock as Clock
import Database.HDBC.PostgreSQL
import Database.HDBC
import Data.ByteString.Internal
import Data.ByteString hiding (map)
import Data.Char
import Data.Word8
import Numeric
exampleData = pack ([0..65536] :: [Word8]) :: ByteString
safeEncode :: ByteString -> ByteString
safeEncode x = pack (convert' =<< unpack x)
where
convert' :: Word8 -> [Word8]
convert' 92 = [92, 92]
convert' x | x >= 32 && x < 128 = [x]
convert' x = 92:map c2w (showIntAtBase 8 intToDigit x "")
runTest = do
conn <- connectPostgreSQL "dbname=db"
t <- Clock.getCurrentTime
withTransaction conn
(\conn -> run conn
"INSERT INTO documents (id, importTime, filename, data, recordCount, parseSuccessful) VALUES (?, ?, ?, ?, ?, ?)"
[toSql (15 :: Int),
toSql t,
toSql ("Demonstration data" :: String),
toSql $ safeEncode exampleData,
toSql (15 :: Int),
toSql (True :: Bool)])