如何从postgresql-query调用pgQuery?求IO monad运行示例
没问题,我来帮你搞定在IO monad里直接用postgresql-query的pgQuery函数这件事。核心是要满足pgQuery需要的两个约束:HasPostgres(获取数据库连接)和MonadLogger(处理日志),下面一步步给你讲清楚,还有完整的示例代码:
第一步:理解约束对应的解决方案
pgQuery的类型签名要求两个关键约束:
HasPostgres m:这个类型类需要你的monad能获取PostgreSQL连接,postgresql-query库已经为ReaderT Connection m提供了实例,所以我们可以用runPgConn函数把需要连接的动作转换成目标monad。MonadLogger m:这个类型类负责日志输出,monad-logger库提供了runStdoutLoggingT函数,可以把带日志的动作转换成IO,同时把日志输出到标准输出。
第二步:补全你的doIt函数
首先把你写的doIt补全,比如返回是否找到匹配的设置(根据查询结果是否非空):
doIt :: (HasPostgres m, MonadLogger m) => Text -> m Bool doIt name = do (val::[Only Int]) <- pgQuery [sqlExp|select setting from pg_settings where name=#{name}|] -- 返回是否存在匹配的设置项 return $ not (null val)
第三步:在IO monad中运行doIt
接下来写一个main函数,把doIt转换成IO动作,步骤包括:建立连接、处理约束、执行查询、清理连接:
首先导入所有必要的模块:
import Database.PostgreSQL.Query (pgQuery, sqlExp, HasPostgres, runPgConn) import Database.PostgreSQL.Simple (Connection, connectPostgreSQL, Only(..), close, withPostgreSQL) import Control.Monad.Logger (MonadLogger, runStdoutLoggingT) import Data.Text (Text)
然后用两种方式实现IO运行:
方式1:手动管理连接
main :: IO () main = do -- 替换成你的PostgreSQL连接字符串 let connStr = "host=localhost dbname=your_db user=your_user password=your_pass port=5432" -- 1. 建立连接 conn <- connectPostgreSQL connStr -- 2. 结合runStdoutLoggingT(处理MonadLogger)和runPgConn(处理HasPostgres) result <- runStdoutLoggingT $ runPgConn conn (doIt "work_mem") -- 3. 输出结果 putStrLn $ "查询是否找到设置: " ++ show result -- 4. 手动关闭连接 close conn
方式2:自动管理连接(更安全)
用withPostgreSQL可以自动在动作结束后关闭连接,避免忘记清理:
main :: IO () main = do let connStr = "host=localhost dbname=your_db user=your_user password=your_pass port=5432" runStdoutLoggingT $ withPostgreSQL connStr $ \conn -> do -- 在withPostgreSQL的回调里执行查询 result <- runPgConn conn (doIt "work_mem") -- 用liftIO把IO动作带到LoggingT monad里 liftIO $ putStrLn $ "查询是否找到设置: " ++ show result
为什么这样可行?
runPgConn conn action:把需要HasPostgres约束的action(这里是doIt)转换成m a,其中m是你传入的monad(这里是LoggingT IO),因为ReaderT Connection m是HasPostgres的实例,runPgConn会把连接注入进去。runStdoutLoggingT:把LoggingT IO a转换成IO a,同时处理日志输出(你会在控制台看到pgQuery生成的SQL日志)。
这样你就不需要用runSqlBuilder转成标准query,直接用pgQuery在IO里运行了。
内容的提问来源于stack exchange,提问作者RandomB
相关产品推荐
相关产品推荐

