我有一个 Haskell 应用程序,作为许多步骤之一,它需要在数据库中存储和检索原始二进制 blob 数据。相反,我并没有完全决定将这些数据存储在普通磁盘文件中,但这确实开始导致另一轮权限问题,所以现在我想使用数据库。
我创建了一个包含 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 的代码后遇到的当前问题。我的错误消息已从上面的编码问题更改为“bytea 类型的输入语法无效”。
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)])