Yesod 中的复合主键
Composite Primary Key in Yesod
我是 Haskell 的新手,现在已经尝试使用 yesod 大约一个星期了。我一直在尝试连接到在 sqlite 中具有复合主键的现有数据库。我设法让代码作为独立应用程序与 Database.Persist.Sqlite
一起使用。
这是使用 persistent-sqlite
.
作为独立应用程序运行的代码
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveGeneric #-}
import Control.Monad.IO.Class (liftIO)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import System.Environment
import Data.Text (Text,pack)
import Data.Time (UTCTime)
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving Show
|]
main :: IO ()
main = do
(path:args) <- getArgs
movies <- runSqlite (pack path) $ do
runMigration migrateAll
selectList [] [Desc MovieTitle]
mapM_ print movies
这是一个人为的例子,但它说明了我的观点。我想要一个由 title
和 year
组成的复合主键。一切都编译得很好, table 是用我需要的模式创建的。当我尝试在带有 persistent-sqlite
的 yesod 应用程序中使用上面定义的 Movie
类型时,出现以下编译时错误
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘toPathPiece’
In the first argument of ‘(:)’, namely ‘(toPathPiece dyn_apvA)’
In the second argument of ‘(:)’, namely
‘((toPathPiece dyn_apvA) : [])’
In the expression:
((Data.Text.pack "entry") : ((toPathPiece dyn_apvA) : []))
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘fromPathPiece’
In the expression: fromPathPiece
In the pattern: fromPathPiece -> Just dyn_apwt
In the pattern: (:) (fromPathPiece -> Just dyn_apwt) []
我被困在这一点上,无法自行继续。我试过搜索,但我只能在不使用 yesod 的情况下找到复合主键的工作示例。我觉得应该可以做到,因为仅使用 persistent-sqlite
的复合主键有效。
下面是 Movie
类型在 config/models
中的定义方式
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving
我自己并没有真正使用过复合主键功能,但这个错误对我来说很有意义。对于任意组合键, Text
没有明显的序列化,因此持久性不会为您生成它。如果您想在 URL 中使用 MovieId
,则需要手动定义 PathPiece
实例,它只是一对用于与 Text
相互转换的函数。
我是 Haskell 的新手,现在已经尝试使用 yesod 大约一个星期了。我一直在尝试连接到在 sqlite 中具有复合主键的现有数据库。我设法让代码作为独立应用程序与 Database.Persist.Sqlite
一起使用。
这是使用 persistent-sqlite
.
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveGeneric #-}
import Control.Monad.IO.Class (liftIO)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import System.Environment
import Data.Text (Text,pack)
import Data.Time (UTCTime)
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving Show
|]
main :: IO ()
main = do
(path:args) <- getArgs
movies <- runSqlite (pack path) $ do
runMigration migrateAll
selectList [] [Desc MovieTitle]
mapM_ print movies
这是一个人为的例子,但它说明了我的观点。我想要一个由 title
和 year
组成的复合主键。一切都编译得很好, table 是用我需要的模式创建的。当我尝试在带有 persistent-sqlite
的 yesod 应用程序中使用上面定义的 Movie
类型时,出现以下编译时错误
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘toPathPiece’
In the first argument of ‘(:)’, namely ‘(toPathPiece dyn_apvA)’
In the second argument of ‘(:)’, namely
‘((toPathPiece dyn_apvA) : [])’
In the expression:
((Data.Text.pack "entry") : ((toPathPiece dyn_apvA) : []))
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘fromPathPiece’
In the expression: fromPathPiece
In the pattern: fromPathPiece -> Just dyn_apwt
In the pattern: (:) (fromPathPiece -> Just dyn_apwt) []
我被困在这一点上,无法自行继续。我试过搜索,但我只能在不使用 yesod 的情况下找到复合主键的工作示例。我觉得应该可以做到,因为仅使用 persistent-sqlite
的复合主键有效。
下面是 Movie
类型在 config/models
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving
我自己并没有真正使用过复合主键功能,但这个错误对我来说很有意义。对于任意组合键, Text
没有明显的序列化,因此持久性不会为您生成它。如果您想在 URL 中使用 MovieId
,则需要手动定义 PathPiece
实例,它只是一对用于与 Text
相互转换的函数。