Esqueletoの利用方法(Legacy版)

Tech > Haskell > データベース

Type-safeにSQLを扱うためのEDSLでバックエンドはPersistentを利用しているライブラリです。

テーブルのJOIN

from関数 の中で、 InnerJoinLeftOuterJoinRightOuterJoin などが利用可能です。

getUsers ::
    Param
    -> Handler ([(Entity UsrMember, Value Text, Value Int)], Int)
getUsers p = runDB $ do
    let pagePerLine = fromIntegral $ unPagePerLine p
        page = fromIntegral $ unPageNum p
        reqId = fromIntegral $ unReqId p
        typeIds = [1, 2]
        (ageFrom, ageTo) = (unAgeFrom p, unAgeTo p)
        baseQuery = from $ \(usrMember `InnerJoin`
                             usrImage `InnerJoin`
                             usrAgeView) -> do
            on $ usrMember ^. UsrMemberUsrMemberId ==. usrAgeView ^. UsrAgeViewUid
            on $ usrMember ^. UsrMemberUsrMemberId ==. usrImage ^. UsrImageUsrId
            where_ $ do
               let reqQuery = usrMember ^. UsrMemberReqId ==. val reqId
                    ageQuery = usrAgeView ^. UsrAgeViewAge >=. val ageFrom
                                  &&. usrAgeView ^. UsrAgeViewAge <=. val ageTo
               usrMember ^. UsrMemberTypeId `in_` valList typeIds
                    &&. (if reqId > 0 then reqQuery else val True)
                    &&. (if ageFrom > 0 && ageTo > 0 then ageQuery else val True)
                    &&. usrImage ^. UsrImageImageDiv ==. val 2
            return
              (
                usrMember
              , usrImage ^. UsrImageFileName
              , usrAgeView ^. UsrAgeViewAge
              )
        baseQueryPage =
            do
                r <- baseQuery
                offset (pagePerLine * page)
                limit pagePerLine
                return r
    cnt <- Import.length <$> select baseQuery
    s <- select baseQueryPage
    return (s,  cnt)

サブクエリ

サブクエリの注意点は、サブクエリの結果が取得できる場合、 subSelect関数 を利用すること、条件によってはサブクエリ結果が取得できない場合は、 subSelectMaybe関数 を利用することです。

getList ::
    Key UsrMember
    -> Handler Int
getList (UsrMemberKey uid) = runDB $ do
    let pagePerLine = 10
        page = 0
    list <- select $ from $ \(um `InnerJoin` mdt) -> do
        let newRec = subSelect $ from $ \mdt -> do
                where_ $ mdt ^. MsgDetailRefUsrMemberId ==. um ^. UsrMemberUsrMemberId
                limit 1
                orderBy [desc (mdt ^. MsgDetailCreateTime)]
                return $ mdt ^. MsgDetailCreateTime
        on $
            um ^. UsrMemberUsrMemberId ==. mdt ^. MsgDetailRefUsrMemberId
        where_ $ do
            um ^. UsrMemberUsrMemberId ==. val uid
            &&.
            um ^. UsrMemberStatusFlag >=. val contractStatusFlag
        orderBy [ desc (um ^. UsrMemberCreateTime)]
        limit pagePerLine
        offset page
        return (newRec, um ^. UsrMemberNickname)
    return 0

補足説明

Value typ

select関数 で最後にreturnされる値は、 「um ^. UsrMemberNickname」で、

return (newRec, um ^. UsrMemberNickname)

モデルで定義されている、UsrMemberのnicknameのフィールドを意味しています、そしてnicknameフィールドが

UsrMember
...
    nickname Text sqltype=varchar(64)

のように宣言されている場合、(Value typ) でtypがText型 (Value Text) で取得できるようになります。

Entity

Entityはテーブル情報そのものを表現しています

return
  (
    usrMember
  , usrImage ^. UsrImageFileName
  , usrAgeView ^. UsrAgeViewAge
  )

usrMemberについては、テーブルすべての項目を取得している書き方で、モデルが

UsrMember
    usrMemberId Int sqltype=bigint default=nextval('usr_member_usr_member_id_seq')
...
    nickname Text sqltype=varchar(64)

のような場合、usrMemberIdは PrimaryAuto Increment とすると

data Entity record =
    Entity
        {
          entityKey :: Key record
        , entityVal :: record
        }

で定義されるように、Primary Keyrecord (実際のレコードデータ) の2つで取得できます。

キーの値を取る場合はパターンマッチで取得するパターンと

func :: Key UsrMember -> Handler ()
func UsrMemberKey pk = do
  ...

Keyを取ってInt64を返す関数として書くこともできます。

fromTblFreeKey :: Key TblFree -> Int64
fromTblFreeKey = unSqlBackendKey . unTblFreeKey

備忘録で書いておきます、気がつけば追加していきます。

githubサンプルコード はこちらに置いてあります。

Posted on 2021-01-15 18:06:05

はじめまして

お茶の国静岡で、焼酎のお茶割なんか罰当たりで飲んだことはありません、常に一番搾りを嗜む静岡極東のBBQerです、最近まわりのエンジニアの方々がお料理を上手にやっている姿を恨めしそうに横目に見ながら、軟骨ピリ辛チクワを食べています、みなさんよろしく。

Posted

Amazon

tags

日本酒池 広井酒店 やがら やっぱた 刺身 丸干し 東京マラソン fpm php82 servant thread spawn Rust Oracle Linux 8 microcode firmware linux openzfs zfs gitea 麒麟 真野鶴 金鶴 日本酒 docker oracle pod podman cli virtualbox VirtualBox epub mobi calibre mask lens ワンライナー php redmine Linux Oracle Map OMap omap map BBQ カテゴリ管理 カテゴリ timestamp date oracle database string 麦焼酎 ダービー process 磨き蒸留 広井酒店、日本酒 芋焼酎 焼酎 ゆるキャン 広井酒店、日本酒池 spring framework java persistent spring session session spring hdbc-odbc persistent-odbc odbc day utctime スィート レマンの森 elm初期化 elm バイク xlr80 esqueleto database xl2tpd strongswan vpn l2tp ipsec 正月 ゲーム grub nginx systemctl portage 豚骨 圧力鍋 yesod-auth-hashdb yesod-auth yesod