13

我一直在尝试找出一种明智的方法来使用持久性在 SQL 后端表示 Haskell 总和类型。

我的目标 Haskell 数据类型是

data Widget = FooWidget Int | BarWidget T.Text

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

我正在使用以下持久数据类型对它们进行建模:

Element
  name    T.Text

Foo
  elementId ElementId
  size      Int

Bar
  elementId ElementId
  colour    T.Text

每个元素只会有一个 Foo 或一个 Bar ,永远不会两者都有。

我想使用 aLeft Outer Join来选择我的所有元素和相应的 Foo OR Bar。我的 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)

但是,当我执行代码时,出现错误:

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

如果我删除第二个加入,给出:

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

代码运行没有错误。我确定这很明显,但我看不出我做错了什么。


编辑:我发现了问题所在;来自文档:

请注意,ON 子句的顺序是颠倒的!您需要以相反的顺序编写您的 ons,因为这有助于可组合性(有关更多详细信息,请参阅 on 的文档)。

以下代码有效(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)

谢谢,

迈克尔

4

1 回答 1

4

按照 Waldheinz 的建议添加作为答案


我发现了问题所在;来自文档:

请注意,ON 子句的顺序是颠倒的!您需要以相反的顺序编写您的 ons,因为这有助于可组合性(有关更多详细信息,请参阅 on 的文档)。

以下代码有效(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)

问候,

迈克尔

于 2015-02-07T00:42:24.990 回答