Yesod + sqlite3可能导致ErrorConstraint SqliteException错误的原因是什么?

时间:2017-04-02 14:49:51

标签: sqlite yesod

什么可能导致以下错误?

 uncaught exception: SqliteException (SQLite3 returned ErrorConstraint while attempting to perform step.)

奇怪的是,大多数规范都因使用withApp的错误而失败。

但是,如果我修改wipeDB中的TestImport.hs来执行

system "rm project-name_test.sqlite3*"
然后突然所有规格再次通过。虽然测试运行时间大约是4-5倍,但不太理想。

可能是wipeDB逻辑(由stack new生成)不够彻底吗?

我试图查看models文件,看看我是否在其中指定了唯一性限制,但我看不到任何不合适的地方。

我评论了models以外的所有内容,除了:

User
    emailAddress Text
    password ByteString
    verified Bool
    verifyKey Text
    resetPasswordKey Text
    deriving Show

Foo
    userA UserId
    userB UserId
    deriving Show

如果有限制,他们会在这个文件中,不是吗?或者可以有其他地方宣布约束?无论如何,例外可能涉及哪些约束?

我还没有像我希望的那样缩小范围,但似乎所有这些都可以追溯到runDB $ insert $ Foo,如果我删除,那么有关的例外就消失了,更多的规格通过,只有少数失败,因为他们希望插入已经发生。它们也因断言失败而失败,而不是ErrorConstraint异常。

如果此错误有多种可能原因,我希望听到这些错误,因为我发现异常比我更加模糊。

1 个答案:

答案 0 :(得分:2)

This是我找到的最佳解决方案。看起来像是“官方”解决方案。

所以在我的项目中我完成了this way

所以现在这是我的wipeDB功能:

wipeDB :: App -> IO ()
wipeDB app = do
    let settings = appSettings app
        logFunc = messageLoggerSource app (appLogger app)

    sqliteConn <- rawConnection (sqlDatabase $ appDatabaseConf settings)
    let infoNoFK = set fkEnabled False $ mkSqliteConnectionInfo ""
        wrapper = wrapConnectionInfo infoNoFK sqliteConn
    pool <- runLoggingT (createSqlPool wrapper 1) logFunc

    flip runSqlPersistMPool pool $ do
        tables <- getTables
        sqlBackend <- ask
        let queries = map (\t -> "DELETE FROM " ++ (connEscapeName sqlBackend $ DBName t)) tables
        forM_ queries (\q -> rawExecute q [])