简体   繁体   English

用Persistent和Esqueleto连接在sql中表示和类型

[英]Representing sum types in sql with Persistent, and Esqueleto joins

I have been trying to figure out a sensible way to represent Haskell sum types in a SQL backend using persistent. 我一直试图找出一种合理的方法来使用持久性来表示SQL后端中的Haskell和类型。

My target Haskell data type is along the lines of 我的目标Haskell数据类型是沿着的

data Widget = FooWidget Int | BarWidget T.Text

data HElement = HElement 
   { name   :: T.Text
   , widget :: Widget
   }

I am modeling these using the following Persistent data types: 我使用以下持久数据类型对它们进行建模:

Element
  name    T.Text

Foo
  elementId ElementId
  size      Int

Bar
  elementId ElementId
  colour    T.Text

There will only ever be either a Foo or a Bar for each Element, never both. 每个元素都只有Foo或Bar,而不是两者。

I want to use a Left Outer Join to select all my elements and the corresponding Foo OR Bar. 我想使用Left Outer Join来选择我的所有元素和相应的Foo OR Bar。 My Esqueleto expression is: 我的Esqueleto表达式是:

select $ 
from $ \(elem `LeftOuterJoin` foo `LeftOuterJoin` bar) -> do
on (just (elem ^. ElementId) ==. foo ?. FooElementId)
on (just (elem ^. ElementId) ==. bar ?. BarElementId)
return (elem, foo, bar)

However, when I execute the code, I get the error: 但是,当我执行代码时,我收到错误:

user error (Postgresql.withStmt': bad result status FatalError (("PGRES_FATAL_ERROR","ERROR:  missing FROM-clause entry for table

If I remove the second join, giving: 如果我删除第二个连接,则给出:

select $ 
from $ \(elem `LeftOuterJoin` foo) -> do
on (just (elem ^. ElementId) ==. foo ?. FooElementId)
return (elem, foo)

The code runs without error. 代码运行没有错误。 I'm sure it's obvious but I can't see what I am doing wrong. 我确定这很明显,但我看不出我做错了什么。


EDIT: I found what the problem was; 编辑:我发现了问题所在; from the docs: 来自文档:

Note carefully that the order of the ON clauses is reversed! 请注意,ON子句的顺序是相反的! You're required to write your ons in reverse order because that helps composability (see the documentation of on for more details). 您需要以相反的顺序编写您的ons,因为这有助于可组合性(有关更多详细信息,请参阅on的文档)。

The following code works (the order of the on expressions reversed): 以下代码有效( on表达式的顺序颠倒过来):

select $
from $ \(elem `LeftOuterJoin` foo `LeftOuterJoin` bar) -> do
on (just (elem ^. ElementId) ==. bar ?. BarElementId)
on (just (elem ^. ElementId) ==. foo ?. FooElementId)
return (elem,foo,bar)

Thanks, 谢谢,

Michael 迈克尔

Adding as an answer as suggested by Waldheinz 根据Waldheinz的建议添加答案


I found what the problem was; 我发现了问题所在; from the docs: 来自文档:

Note carefully that the order of the ON clauses is reversed! 请注意,ON子句的顺序是相反的! You're required to write your ons in reverse order because that helps composability (see the documentation of on for more details). 您需要以相反的顺序编写您的ons,因为这有助于可组合性(有关更多详细信息,请参阅on的文档)。

The following code works (the order of the on expressions reversed): 以下代码有效( on表达式的顺序颠倒过来):

select $
from $ \(elem `LeftOuterJoin` foo `LeftOuterJoin` bar) -> do
on (just (elem ^. ElementId) ==. bar ?. BarElementId)
on (just (elem ^. ElementId) ==. foo ?. FooElementId)
return (elem,foo,bar)

Regards, 问候,

Michael 迈克尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM