我试图在带有MySQL后端的Persistent模型的字段中存储markdown。我已将用例分解为:
模型:
TestModel
content Markdown
Model.hs:
import Text.Markdown (Markdown)
import Yesod.Text.Markdown ()
....
这似乎可以创建正确的迁移:
mysql> show columns in test_model;
+---------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| content | text | NO | | NULL | |
+---------+------------+------+-----+---------+----------------+
但是,当我尝试从此表中检索数据时,我遇到了一个例外。下面的示例来自cabal repl
,但在应用程序运行时会发生同样的情况:
repl> testid <- db $ insert $ TestModel $ Markdown "# Hello world"
[Debug#SQL] INSERT INTO `test_model`(`content`) VALUES(?); [PersistText "# Hello world"]
repl> testmodel <- db $ get testid
[Debug#SQL] SELECT `content` FROM `test_model` WHERE `id`=?; [PersistInt64 2]
*** Exception: runFakeHandler issue: InternalError "get TestModelKey {unTestModelKey = SqlBackendKey {unSqlBackendKey = 2}}: field content: Not a PersistText value"
我的第一个猜测是TestModel构造函数的值是错误的,但即使在表单中使用markdownField
创建对象时也会出现相同的错误:
testModelForm :: AForm Handler TestModel
testModelForm = TestModel
<$> areq markdownField "Content" Nothing
getTestModelR :: TestModelId -> Handler Html
getTestModelR testModelId = do
testmodel <- runDB $ get404 testModelId
....
08/Aug/2015:12:44:33 -0700 [Error#yesod-core] get TestModelKey {unTestModelKey = SqlBackendKey {unSqlBackendKey = 2}}: field content: Not a PersistText value @(yesod-core-1.4.12:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:577:5)
之前是否有人见过此例外并知道如何处理它?我似乎找到的这个错误的唯一文档是yesod-text-markdown
的{{3}}。
答案 0 :(得分:1)
原来这是由于persistent-mysql
中已修复的persistent-mysql-2.3
包中的错误引起的。
以下是感兴趣的人的根本原因:
MySQL C库(以及mysql
所依赖的Haskell persistent-mysql
包扩展)并不区分类型级别的二进制和文本数据。因此,如果您将TEXT
值保存到数据库,那么当它被持久查找时,它似乎是二进制数据(PersistByteString
)。
我通过检查列的字符集在#451中修复了这个问题,MySQL API文档建议将其作为适当的解决方案。
有关详情,请参阅拉取请求或this issue。
感谢您提出这个问题;我不会意识到还有一个错误。