Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql a如何通过HDBC将二进制数据放入postgres?_Postgresql_Haskell_Hdbc - Fatal编程技术网

Postgresql a如何通过HDBC将二进制数据放入postgres?

Postgresql a如何通过HDBC将二进制数据放入postgres?,postgresql,haskell,hdbc,Postgresql,Haskell,Hdbc,我有一个Haskell应用程序,作为许多步骤之一,它需要在数据库中存储和检索原始二进制blob数据。我并没有完全放弃将数据存储在普通磁盘文件中的决定,但这确实会导致额外的权限问题,所以现在我想使用数据库 我创建了一个表,其列类型为bytea 我的记忆中有一个懒惰的拜特铃 当我打这样的电话时 run conn "INSERT INTO documents VALUES (?)" [toSql $ rawData mydoc] postgres对这些数据有点生气。确切的错误消息是 invalid

我有一个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类型的输入语法无效”

模块DBMS测试,其中
将符合条件的Data.Time.Clock作为时钟导入
导入Database.HDBC.PostgreSQL
导入数据库.HDBC
导入Data.ByteString.Internal
导入数据。ByteString隐藏(映射)
导入数据.Char
导入数据.Word8
输入数字
exampleData=pack([0..65536]:[Word8])::ByteString
safeEncode::ByteString->ByteString

safeEncode x=pack(convert'=我相信这是HDBC postgresql中的一个错误。我可以解释为什么我会这样认为,并可以为您提供一个解决方案,我将其组合起来并进行测试


我希望HDBC postgresql将bytestring转换为要插入的适当格式,但您可以快速验证它是否希望bytestring保存数据的八进制退格转义值。例如

run conn "INSERT INTO documents VALUES (?)" [toSql $ B.pack [92, 0x31, 0x30, 0x31]]
将单个字符“A”插入数据库!只有当您意识到[92,0x31,0x30,0x31]是“\101”的ascii表示形式,“\101”是“A”的八进制表示形式时,这才有意义。因为八进制退格转义字符串保证允许直接传递32-127范围内的值(详细信息请参见评论中提供的Richard Huxton链接),insert查询实际上对标准英文文本工作正常,可能没有引起注意

run conn "INSERT INTO documents VALUES (?)" [toSql $ B.pack [65]]
还插入“A”。大于127的值不保证有效,并根据使用的字符编码进行解释。如果查看HDBC postgresql代码或查询日志,可以看到它正在将变量“client_encoding”设置为utf8。因此,来自bytestring的数据应为有效的utf8,即当它看到一个不能作为utf8字符存在的序列时,d会抱怨

正确的修复方法是等待HDBC postgresql人员修复错误,但在此期间,您可以使用此代码作为解决方法

import Data.ByteString.Internal
import Data.Char
import Data.Word8
import Numeric
import Text.Printf

convert::B.ByteString->B.ByteString
convert x = B.pack (convert' =<< B.unpack x)
          where
            convert'::Word8->[Word8]
            convert' 92 = [92, 92]
            convert' x | x >= 32 && x < 128 = [x]
            convert' x = 92:map c2w (printf "%03o" x) 

我从未使用过HDBC,但我在postgresql simple方面取得了成功(不过我还没有尝试过bytea数据)到目前为止,还没有。我已经有很多代码,并且已经有了这个API的句柄。我现在负担不起切换的成本。在PostgreSQL端打开查询日志,看看数据是如何转义的。它应该是八进制(旧格式)或十六进制(新格式)。您使用的是HDBC postgresql还是HDBC odbc?我建议您尝试使用HDBC odbc来使用postgresql,因为绑定更发达(更快)。我相信这在postgresql simple中也是一个问题。至少我认为基本上是相同的代码,但我得到了相同的错误。我已经向hdbc postgresql提交了一份错误报告,如果我错误地认为这是一个错误,他们很快就会纠正我的错误!看,我已经实现了这一点,区别在于我的ByteString是一个懒惰的ByteString。现在我刚收到postgres告诉我,我为bytea类型提供了无效的输入语法。即使我将日志记录设置为“all”,查询日志中也没有其他信息。虽然我也将日志记录设置为syslog,所以在这种情况下,它发送的数据可能会更少。@SavanniD'Gerinel-你能让它使用严格的ByTestRing吗?这将是如果我知道这一点,调试就更容易了……不,我不能。我添加了大量示例代码来说明我在做什么。如果您愿意,我还可以添加库版本。@SavanniD'Gerinel-我的代码中有一个bug,并修复了它……
ShowIntbase 8 intToDigit x”“
没有添加前导零,因此低于32的字节被破坏(请记住,32-127是刚刚通过的)。此外,在您的示例中,您使用了
[1..65536]:[Word8]
。这并不是您认为的那样。请记住,
Word8
只从0-255开始,strangly Haskell只是截断大于255的数字的转换,而不是抱怨,因此
([0..65536]:[Word8])=[0..0]:::[Word8])=[0]
。如果要测试全部字符,请使用
[0..255]::[Word8]
import Data.ByteString.Internal
import Data.Char
import Data.Word8
import Numeric
import Text.Printf

convert::B.ByteString->B.ByteString
convert x = B.pack (convert' =<< B.unpack x)
          where
            convert'::Word8->[Word8]
            convert' 92 = [92, 92]
            convert' x | x >= 32 && x < 128 = [x]
            convert' x = 92:map c2w (printf "%03o" x) 
run conn "INSERT INTO documents VALUES (?)" [toSql $ convert $ rawData mydoc]