【发布时间】:2013-12-18 03:14:47
【问题描述】:
我有一个 Haskell 应用程序,作为许多步骤之一,它需要在数据库中存储和检索原始二进制 blob 数据。相反,我并没有完全决定将这些数据存储在普通磁盘文件中,但这确实会导致另一轮权限问题,所以现在我想使用数据库。
我创建了一个包含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)])
【问题讨论】:
-
我从未使用过 HDBC,但我使用 postgresql-simple 取得了成功? (虽然我还没有尝试过使用 bytea 数据。)
-
到目前为止,没有。我已经有很多代码并且已经掌握了这个 API。我现在负担不起转换的费用。
-
在 PostgreSQL 端开启查询日志,看看数据是如何被转义的。它应该是八进制(旧格式)或十六进制(新格式)。 postgresql.org/docs/current/static/datatype-binary.html#AEN5318
-
您使用的是 HDBC-postgresql 还是 HDBC-odbc?我建议您尝试使用 HDBC-odbc 来使用 postgresql,因为绑定更发达(更快)。
-
我相信这也是 postgresql-simple 中的一个问题。至少我得到了与我认为本质上相同的代码相同的错误。
标签: postgresql haskell hdbc