我刚刚发现这种行为的根源不是由使用sql=…
引起的,而是我使用第一个表的主键作为外来的和主键。 / p>
Post
topic String
deriving Show Eq
PostContent
Id PostId
content String
deriving Show Eq
所以问题仍然存在:
我能否以某种方式表达主键是外键? - 从SQL的角度来看,这是有道理的(至少我是这么认为的)?
我正在通过simon marlow Fun With HAXL pt1向oracle / docker做一个haxl示例的端口,以获得概念验证。
我正在使用现有的sql脚本来生成db(就像在我的手中没有db表的现实情况一样) - 我有以下db布局
| POSTID NUMBER | POSTDATE DATE | POSTTOPIC VARCHAR2(512 CHAR) |
| POSTID NUMBER | CONTENT CLOB |
| POSTID NUMBER | VIEWS INT |
当然,我想表达POSTID
是外国人和外国人的关系。相应的haskell持久性postcontent
中的postview
和QuasiQuoter
中的唯一键。关注yesod-book,从维基链接的wiki和test cases。
我创建了以下模板haskell splice:
share [ mkPersist sqlSettings {mpsGeneric = False} , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings {mpsGeneric = False}] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
date UTCTime sql=POSTDATE
topic Text sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
Id PostId sql=POSTID
content Text sql=CONTENT
deriving Show Eq
PostViews sql=POSTVIEWS
Id PostId sql=POSTID
views Int sql=VIEWS
deriving Show Eq
|]
编译错误
error:
• Not in scope: type constructor or class ‘PostId’
• In the quasi-quotation:
[persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
date UTCTime sql=POSTDATE
topic Text sql=POSTTOPIC
deriving Show Eq
PostContent
Id PostId sql=POSTID
content Text sql=CONTENT
deriving Show Eq
PostViews
Id PostId sql=POSTID
views Int sql=VIEWS
deriving Show Eq
|]
有一点需要注意以下测试用例准引用 - 工作,
Citizen
name String
age Int Maybe
deriving Eq Show
Address
address String
country String
deriving Eq Show
CitizenAddress
citizen CitizenId
address AddressId
Primary citizen address
deriving Eq Show
这是一个简单的例子,可以重现错误和正在运行的一些工作版本(并相应地更改#define
行
> stack runhaskell --package persistent-template minimal.hs
minimal.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE CPP #-}
module Minimal where
import Database.Persist.TH
#define FAILS
main :: IO ()
main = putStrLn "It works"
#ifdef WORKS
share [ mkPersist sqlSettings {mpsGeneric = False} , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings {mpsGeneric = False}] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
|]
#endif
#ifdef ALSOWORKS
share [ mkPersist sqlSettings {mpsGeneric = False} , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings {mpsGeneric = False}] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
post PostId sql=POSTID
content String sql=POSTCONTENT
deriving Show Eq
|]
#endif
#ifdef FAILS
share [ mkPersist sqlSettings {mpsGeneric = False} , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings {mpsGeneric = False}] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
Id PostId sql=POSTID
content String sql=POSTCONTENT
deriving Show Eq
|]
#endif
-- UPDATE
#ifdef FAILSTOO
share [ mkPersist sqlSettings {mpsGeneric = False} , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings {mpsGeneric = False}] [persistUpperCase|
Post
topic String
deriving Show Eq
PostContent
Id PostId
content String
deriving Show Eq
|]
#endif
答案 0 :(得分:4)
我能否以某种方式表达主键是外键?
是。假设Sqlite为数据库的示例代码示例:
#!/usr/bin/env stack
{- stack
--resolver lts-7.14
--install-ghc
runghc
--package yesod
--package yesod-core
--package blaze-html
--package text
--package persistent
--package persistent-template
--package persistent-sqlite
--package shakespeare
--package aeson
-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Logger (runStderrLoggingT)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
share
[mkPersist sqlSettings, mkMigrate "migrateAll"]
[persistLowerCase|
Post
topic String
deriving Show
PostContent
pid PostId
Primary pid
deriving Show
|]
main :: IO ()
main = mockMigration migrateAll
执行时,你得到这个:
CREATE TABLE "post"("id" INTEGER PRIMARY KEY,"topic" VARCHAR NOT NULL)
CREATE TABLE "post_content"("pid" INTEGER NOT NULL REFERENCES "post", PRIMARY KEY ("pid"))
您可以在上面的示例中看到表pid
中的post_content
列既是主键又是外键。