Представление типов сумм в sql с Persistent, а также объединение Esqueleto

Я пытаюсь выяснить разумный способ представления типов сумм Haskell в бэкэнд SQL с использованием постоянных.

Мой целевой тип данных 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 для каждого элемента, никогда не оба.

Я хочу использовать Left Outer Join для выбора всех моих элементов и соответствующей панели Foo OR. Выражение 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)

Код работает без ошибок. Я уверен, что это очевидно, но я не вижу, что я делаю неправильно.


EDIT: я нашел, что проблема; из документов:

Обратите внимание, что порядок предложений 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)

Спасибо,

Майкл

Ответ 1

Добавление в качестве ответа, предложенного Вальдхайнсом


Я понял, в чем проблема; из документов:

Обратите внимание, что порядок предложений 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)

Привет,

Майкл