对 Yesod 中的 selectOneMany 感到困惑

2023-12-14

甜蜜但简单,持久连接是如何工作的?考虑以下模型:

Person
    number Int
    numberOfEyes Int
    firstName FirstnamesId
    lastName LastnamesId
Lastnames
    lastname String
Firstnames
    firstname String

假设我只有一个人的号码,我如何检索他的全名和眼睛的数量?

我尝试浏览haskellers.org 来源但找不到任何连接的示例。我还查看了关于连接的章节在yesod书中,但这只让我眼花缭乱。我的 Haskell 知识水平很低,所以要温柔。


以下是具有相同结果类型的两种方法:

  1. 新类型的 sql,基于“埃斯克莱托“ Felipe Lessa 的软件包是基于持久性的

  2. 和之前的rawSql方式

    只需添加 1 或 2 作为测试参数


{- file prova.hs-}
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts, ConstraintKinds, ScopedTypeVariables #-}
import Prelude hiding (catch)
import Control.Exception  
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import Database.Persist.Quasi
import Database.Esqueleto as Esql
import Database.Persist.GenericSql (SqlPersist, rawSql)
import Control.Monad.Logger (MonadLogger)
import Control.Monad.Trans.Resource (MonadResourceBase)
import System.Environment (getProgName, getArgs)   
import System.Exit (exitSuccess, exitWith, ExitCode(..))
import Text.Printf (printf)

import QQStr(str)  -- heredoc quasiquoter module

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
Person
    number Int
    numberOfEyes Int
    firstName FirstnamesId
    lastName LastnamesId
    UniquePersonNumber number 
    deriving Show

Lastnames
    lastname String
    deriving Show

Firstnames
    firstname String
    deriving Show
|]

-- the esqueleto way

-- with this type annotation it could be run in a yesod handler with ''runDB''
getPersonInfoByNumber :: (PersistQuery SqlPersist m, MonadLogger m, MonadResourceBase m) => Int -> SqlPersist m (Maybe (Int, String, String))
getPersonInfoByNumber pNumber = do
    result <- select $ from $ \(fn `InnerJoin` p `InnerJoin` ln) -> do
            on ((p ^. PersonFirstName) Esql.==. (fn ^. FirstnamesId))
            on ((p ^. PersonLastName) Esql.==. (ln ^. LastnamesId))
            where_ ((p ^. PersonNumber) Esql.==. val pNumber)
            return (p , fn, ln)

    case result of
        [(Entity _ p, Entity _ fn, Entity _ ln)] -> return $ Just (personNumberOfEyes p, firstnamesFirstname fn, lastnamesLastname ln)
        _ -> return Nothing

-- the rawSql way

stmt = [str|SELECT ??, ??, ??
                          FROM Person, Lastnames, Firstnames
                          ON Person.firstName = Firstnames.id
                          AND Person.lastName = Lastnames.id
                          WHERE Person.number = ?
                         |]
                         
getPersonInfoByNumberRaw :: (PersistQuery SqlPersist m, MonadLogger m, MonadResourceBase m) => Int -> SqlPersist m (Maybe (Int, String, String))
getPersonInfoByNumberRaw pNumber = do
    result <- rawSql stmt [toPersistValue pNumber]

    case result of
        [(Entity _ p, Entity _ fn, Entity _ ln)] -> return $ Just (personNumberOfEyes p, firstnamesFirstname fn, lastnamesLastname ln)
        _ -> return Nothing

        
main :: IO ()
main = do
    args <- getArgs
    nomProg <- getProgName
    case args of
        [] -> do
             printf "%s: just specify 1 for esqueleto or 2 for rawSql.\n" nomProg
             exitWith (ExitFailure 1)

        [arg] -> (withSqliteConn ":memory:" $ runSqlConn $ do
              runMigration migrateAll
 
              let myNumber = 5
              fnId <- insert $ Firstnames "John"
              lnId <- insert $ Lastnames "Doe"

              -- in case of insert collision, because of UniquePersonNumber constraint
              --    insertUnique does not throw exceptions, returns success in a Maybe result
              --    insert would throw an exception 

              maybePersId <- insertUnique $ Person {personNumber = myNumber, personNumberOfEyes=2,
                                                personFirstName = fnId, personLastName = lnId}

              info <- case arg of
                          "1" -> getPersonInfoByNumber myNumber
                          _ -> getPersonInfoByNumberRaw myNumber
              liftIO $ putStrLn $ show info
              )
              `catch` (\(excep::SomeException) -> 
                               putStrLn $ "AppSqlError: " ++ show excep)  

Heredoc quasiquoter 的额外模块

module QQStr(str) where

import Prelude
import Language.Haskell.TH
import Language.Haskell.TH.Quote

str = QuasiQuoter { quoteExp = stringE, quotePat = undefined
                  , quoteType = undefined, quoteDec = undefined }

执行:

gabi64@zotac-ion:~/webs/yesod/prova$ ./cabal-dev/bin/prova 1
Migrating: CREATE TABLE "Person"("id" INTEGER PRIMARY KEY,"number" INTEGER NOT NULL,"numberOfEyes" INTEGER NOT NULL,"firstName" INTEGER NOT NULL REFERENCES "Firstnames","lastName" INTEGER NOT NULL REFERENCES "Lastnames")
Migrating: CREATE TABLE "Lastnames"("id" INTEGER PRIMARY KEY,"lastname" VARCHAR NOT NULL)
Migrating: CREATE TABLE "Firstnames"("id" INTEGER PRIMARY KEY,"firstname" VARCHAR NOT NULL)
Just (2,"John","Doe")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对 Yesod 中的 selectOneMany 感到困惑 的相关文章

  • 如何知道 Solr Optimize 何时完成?

    我正在使用 Solr php client 通过 php 与 Solr 进行通信 这段代码触发solr优化命令 solr gt optimize 请问有没有什么方法可以确定优化完成了 这都是因为我的网站上有一个管理页面 我每天必须手动优化
  • 在 Haskell 中等待然后检测按键的简单方法是什么?

    我对 Haskell 还很陌生 所以我正在寻找一种简单的方法来检测按键 而不是使用getLine 如果有人知道任何库 或者知道一些这样做的技巧 那就太好了 如果有更好的地方可以问这个问题 请直接告诉我 我将不胜感激 如果您不想阻止 可以使用
  • C# IEnumerator/yield 结构可能不好?

    背景 我从数据库中获取了一堆字符串 我想返回它们 传统上 它会是这样的 public List
  • Haskell 单例:我们可以通过 SNat 获得什么

    我正在尝试使用 Haskell 单例 在论文中使用单例进行依赖类型编程 http cs brynmawr edu rae papers 2012 singletons paper pdf并在他的博客文章中单例 v0 9 发布 https t
  • 应用交换律

    带有效果的应用程序编程 http staff city ac uk ross papers Applicative html麦克布莱德和帕特森的论文提出了互换法 u lt gt pure x pure f gt f x lt gt u 为了
  • Haskell,范围缩小到无步骤[重复]

    这个问题在这里已经有答案了 为什么在 Haskell 中工作范围不能降低到没有步骤 7 1 gt 但只工作这个 7 6 1 gt 7 6 5 4 3 2 1 Haskell 无法知道您想要执行 1 除非您给出提示 在某些情况下 您可能需要一
  • Haskell 真的是纯粹的吗(有任何语言可以处理系统外的输入和输出)吗?

    在谈到函数式编程中的 Monad 后 该功能是否真的使语言变得纯粹 或者它只是黑板数学之外的现实世界中计算机系统推理的另一张 免狱卡 EDIT 这不是有人在这篇文章中所说的火焰诱饵 而是一个真正的问题 我希望有人能用它来击倒我并说 证明 它
  • 将 SQL Server 数据库合并为 1

    我需要将 20 个具有相同结构的数据库合并为 1 个数据库 我看到了这个帖子 以最小的延迟将来自许多不同数据库的数据整合到一个数据库中 https stackoverflow com questions 2537986 consolidat
  • 可以通过Data.Function.fix来表达变形吗?

    我有这个可爱的fixana这里的函数执行速度比她的姐妹快 5 倍左右ana 我有一个criterion报告支持我这一点 ana alg Fix fmap ana alg alg fixana alg fix f gt Fix fmap f
  • Java - 如何批量插入和更新数据库

    我想在一个PreparedStatement 中批量处理多种类型的数据库调用 这可能吗 有没有办法做类似的事情 PreparedStatement pstmt connection prepareStatement 哪里的 可以是INSER
  • 如何在 TH 拼接中复制 'name 的行为

    考虑这个 Haskell 文件 LANGUAGE TemplateHaskell OPTIONS GHC fplugin Test Inspection Plugin module Text main where import Test I
  • 清理 couchdb 并重新启动

    清理命令是什么CouchDB请 如果我想disable and re start我的CouchDB命令是什么 Thanks CouchDB 可以从以下位置启动 停止 重新启动 etc init d couchdb or etc rc d c
  • 长 IN 子句是代码异味吗?

    简单的问题 想知道长 IN 子句是否有代码味道 我真的不知道如何证明它的合理性 除了我认为的味道之外 我无法解释为什么它有味道 select name code capital population flower bird from us
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 播种方法是插入具有 NULL 值的附加实体

    我突然出现这种奇怪的行为 我在版本控制 tfs 中比较了我的文件 以确保我没有更改任何内容 也没有发现任何不同 我正在用一些元数据播种我的数据库 我发现它有一个我以前从未见过的非常奇怪的行为 我正在插入一个实体 产品 它会插入该实体2 ti
  • 在 MongoDB 中查找 7 天前的记录

    我有一个包含对象的集合 如下所示 1 id ObjectId 551c6605e4c6ac495c923aab sender id ObjectId 551c6605e4c6ac495c923aac rep sender id 38 sen
  • 是否有一个基于对象身份的、线程安全的记忆库?

    我知道记忆化似乎是堆栈溢出的 haskell 标签上的一个长期话题 但我think以前没有人问过这个问题 我知道 Haskell 有几个不同的 现成 记忆库 memo combinators 和 memotrie 包 利用涉及惰性无限数据结
  • 将 Either 列表转换为其中包含列表的 Either 列表

    我是 Haskell 的初学者 我正在编写一些使用 Haskell 的代码Either https hackage haskell org package base 4 9 0 0 docs Data Either html用于错误处理 E
  • 在 DataGrip JetBrains 中创建新数据库

    任何人都知道如何创建新数据库DataGrip https goo gl 99xqGb JetBrains 的数据库 IDE 找不到DataGrip 帮助页面 https goo gl pnFpGS In 数据夹2017 1 https bl
  • Haskell 中的相互递归求值器

    Update 我已经添加一个答案 https stackoverflow com questions 3524485 mutually recursive evaluator in haskell 4504200 4504200这描述了我的

随机推荐

  • 在C中使用scanf读取一定数量的字符?

    我无法接受来自文本文件的输入 我的程序应该读取用户指定的字符串 并且该字符串的长度在运行时确定 当用户运行程序 手动输入值 时它工作正常 但是当我运行老师的文本文件时 它会陷入无限循环 对于这个例子 当我输入 4 个字符并且他在文件中的输入
  • 在特定位置创建 Docker 卷

    我可以告诉 Docker 在主机上的特定位置创建卷吗 主机有一些存储限制 我希望将卷存储在 data代替 var lib docker vfs dir 这甚至没有在文档所以我怀疑我误解了什么 您想使用与默认目录不同的目录吗 var lib
  • 获取 ssl 端点时出现 RCurl 错误

    RCurl 给了我一个error 1411809D SSL routines SSL CHECK SERVERHELLO TLSEXT tls invalid ecpointformat list当我尝试通过 SSL 连接到 https 不
  • jQuery/Javascript 函数清除表单的所有字段[重复]

    这个问题在这里已经有答案了 我正在寻找一个 jQuery 函数 它可以在提交表单后清除表单的所有字段 我没有任何 HTML 代码可以显示 我需要一些通用的东西 你能帮我吗 Thanks Note 这个答案与重置表单字段相关 而不是清除字段
  • Java Applet 部署、ClassNotFoundException(初级类)

    这让我陷入困境 我已经检查并重新检查了拼写和路径 我尝试了几乎所有路径组合 包括相对路径 绝对路径和完整 http 路径 尝试加载 Java 小程序时 我继续收到以下错误 java lang ClassNotFoundException A
  • 这是在 cloudbuild.yaml 文件中编写 if..else 语句的正确方法吗?

    我正在尝试使用 cloudbuild yaml 部署云功能 如果我不使用任何条件语句 它就可以正常工作 当我执行 cloudbuild yaml 文件时遇到错误if conditional陈述 正确的写法是什么 下面是我的代码 steps
  • 在片段内添加日期选择器片段

    我正在尝试在片段内创建日期选择器对话框 主要片段 public class DataFragment extends Fragment implements DatePickerDialog OnDateSetListener privat
  • Libgdx 如何使用手机方向在多个轴上旋转 3D 模型

    我正在尝试使用手机的加速计同时在多个轴上旋转 3D 模型 当我这样做时 我使用setToRotation 然而 这一次只能执行一个轴 例如 ModelInstance modelInstance instances first ROLL m
  • 使用 VS2017 安装程序项目安装 vcredist_x64

    我目前想为 VS2017 项目创建一个安装程序 该项目的先决条件是 vcredist x64 要创建我已经安装的安装程序 ClickOnce 发布 通过 VS2017 安装程序 Microsoft Visual Studio 2017 安装
  • 连接PHP源代码并将表单提交到MySQL数据库

    我正在尝试学习 PHP 并尝试将 MySQL 数据库与我的 PHP 代码连接起来 以创建一个提交表单 让我可以将数据输入到数据库中 我的问题是源代码正在连接 但 HTML 没有将变量发布到 PHP 文件 我真的需要一些帮助 这是我的 HTM
  • Google BigQuery 架构与使用 load_table_from_dataframe 的数字数据类型发生冲突(pyarrow 错误)

    当我将数字数据 int64 或 float64 从 Pandas 数据帧上传到 数字 Google BigQuery 数据类型 pyarrow lib ArrowInvalid 获得长度为 8 的字节串 预期为 16 我尝试更改 Panda
  • RSpec测试数据库索引

    有没有办法用 RSpec 测试数据库索引是否存在 我在用着friendly id gem我经常忘记为 slug 字段创建数据库索引 因此 我想将其包含在我的 RSpec 测试中 您可以使用index exists check unique通
  • 调试时在 pool.close() 上抛出异常,但在运行时不会抛出异常

    我认为我在 Python 2 7 中处理这个问题时没有遇到这个问题 但是在 3 7 中调试时 Python 会抛出异常pool close 叫做 这是该函数的相关部分 pool multiprocessing Pool 6 iterator
  • 将 XYZ 文件中的不规则 3D 数据插值到规则网格

    我有一个包含大量 3D 坐标的 xyz 文件 如下所示 370373 771 6535261 431 2 908 370373 788 6535261 441 2 911 370373 787 6535261 442 2 909 37037
  • 如何使用 jQuery 删除父元素

    我的 jsp 中有一些列表项标签 每个列表项内部都有一些元素 包括一个称为 删除 的链接 a 标签 我想要的只是在单击链接时删除整个列表项 这是我的代码的结构 a click function event event preventDefa
  • MongoDB根据对象成员过滤对象数组内容

    我有以下对象数组 想知道是否有一种方法可以过滤结果 仅返回 QtyIn 记录或仅返回 QtyOut 记录 任何提示都将受到高度赞赏 感谢您的帮助 warehouseID 1234 transactions qtyIn 10 transDat
  • Python - beautifulsoup - 如何处理丢失的结束标签

    我想使用 beautifulsoup 从 html 代码中抓取表格 html 的片段如下所示 使用时table findAll tr 我得到整个表 而不仅仅是行 可能是因为 html 代码中缺少结束标签 table border 0 cel
  • Django FormWizards:如何在表单之间轻松传递用户输入的数据?

    我正在使用 Django 1 4 3 中的 FormWizard 功能 我已经成功创建了一个 4 步表单 在表单的前 3 个步骤中 它正确地从用户那里获取信息 验证信息等 在第 4 步中 它现在只显示一个 确认 按钮 没有其他的 当您在第
  • 连接到 Poloniex Push-API

    我想连接到Poloniex 的推送 API 他们在他们的页面上写着以下内容 要使用推送 API 请连接到 wss api poloniex com 并订阅所需的提要 wss WebSocket 安全 gt SSL 保护 他们还给出了 Nod
  • 对 Yesod 中的 selectOneMany 感到困惑

    甜蜜但简单 持久连接是如何工作的 考虑以下模型 Person number Int numberOfEyes Int firstName FirstnamesId lastName LastnamesId Lastnames lastnam