如何使用 Persistent 启用自动记录 SQL 语句

Posted

技术标签:

【中文标题】如何使用 Persistent 启用自动记录 SQL 语句【英文标题】:How to enable automatic logging of SQL statements with Persistent 【发布时间】:2015-05-13 12:32:32 【问题描述】:

我已经搜索了这个问题的明确答案,但还没有找到 - 如何启用对持久执行的 SQL 语句的自动日志记录?有人可以给我一个小示例程序吗?

以下是当前没有日志记录的示例程序。如何启用登录?

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
    Person
    name Text
    status Text Maybe
    deriving Show
|]

main :: IO ()
main = runSqlite ":memory:" $ do
    runMigration migrateAll
    insert (Person "Oliver Charles" Nothing)
    insert (Person "Jon Snow" Nothing)
    insert (Person "Marky Mark" (Just "helloo helloo"))
    noStatusPeople >>= mapM_ (liftIO . print)
    where
        noStatusPeople =
            select $ from $ \person -> do
                where_ (person ^. PersonStatus ==. val Nothing)
                return (person ^. PersonName)

【问题讨论】:

【参考方案1】:

您需要在实现 MonadLogger 而不仅仅是 IO 的 Monad 中调用您的 SQL 代码。 (见http://hackage.haskell.org/package/monad-logger-0.3.13.1/docs/Control-Monad-Logger.html#v:runStdoutLoggingT)。但是,runSqlite 已经为您设置了日志记录(无...),因此您需要使用较低级别的函数 withSqliteConn。 例如,如果您将代码更改为:

import Control.Monad.Logger
import Control.Monad.Trans.Resource

runResourceT $ runStdoutLoggingT $ withSqliteConn ":memory:" . runSqlConn  $ do...

(通过对资源和 monad-logger 的适当依赖),您可以将 SQL 语句写入标准输出。

作为一个真实的例子,看看我的 scion-class-browser 项目: 在https://github.com/JPMoresmau/scion-class-browser/blob/5ab9c7576f8faf93299826e72defe70dd5b6dd6f/src/Server/PersistentCommands.hs#L93 中,您会看到对 runSqlite 的调用。 runLogging 是一个辅助函数,用于在记录或不记录之间切换,在https://github.com/JPMoresmau/scion-class-browser/blob/f7f2ab0de4f4edb01b307411abf0aa951a3c7c48/src/Scion/PersistentBrowser/DbTypes.hs#L16 中定义(当前构建版本不记录,替换为注释掉的代码)。

当然,您可以编写自己的 MonadLogger 实现,而不是使用简单的转储到 stdout 或 stderr。

附带说明一下,您的代码不会打印出匹配的记录,因为您不应该与 val Nothing 进行比较,而是使用 isNothing:

where_ (isNothing $ person ^. PersonStatus)

【讨论】:

我可能遗漏了一些东西。我尝试输入您的代码,但似乎没有效果。以下是正确的吗? main :: IO ()main = runResourceT $ runStdoutLoggingT $ runSqlite ":memory:" $ do输出还是只有-Migrating: CREATE TABLE "person"("id" INTEGER PRIMARY KEY,"name" VARCHAR NOT NULL,"status" VARCHAR NULL) 对不起,我的错误,runSqlLite 已经设置了日志记录(无),所以您需要使用较低级别的函数。我已经更新了我的答案。 成功了!谢谢!是的,我意识到我应该使用isNothing,这是我在没有 SQL 日志记录的情况下花了一段时间才找到并提示这个问题的错误 :) @JPMoresmau 你知道如何在 yesod 项目中做到这一点吗?看来我应该更改此行logFunc = messageLoggerSource tempFoundation appLogger

以上是关于如何使用 Persistent 启用自动记录 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何在终结器中激活自动记录?

如何使用 Apache HttpClient 5 启用线路日志记录

如何使用 terraform 为自动创建的 GKE 集群和服务防火墙规则启用 Logconfig

mysql 统计信息记录

70-persistent-net.rules无法自动生成,解决方法

kvm命令学习记录