Экто фрагмент без скобок - PullRequest
0 голосов
/ 04 мая 2018

Структура таблицы My Postgres:

   id   | stuff                                                                                                                                                                                                        
--------+------------------------------------------------------------
  123   | {"type1": {"ref": "ref_1", "...": "..."}, "type2": {"ref": "ref_1", "...": "..."}}

Я бы хотел запросить ref в каждом типе материала, у меня есть рабочий SQL-запрос для этого:

SELECT * FROM "stuff" AS c0 CROSS JOIN jsonb_each(c0."stuff") AS f1 WHERE value->>'ref' = 'ref_1';

Но используя этот экто-запрос:

(from c in Stuff,
  join: fragment("jsonb_each(?)", c.stuff),
  where: fragment("value->>'ref' = ?", ^ref)
)
|> Repo.all

Я получаю синтаксическую ошибку Postgres в операторе CROSS JOIN:

** (Postgrex.Error) ERROR 42601 (syntax_error): syntax error at or near ")"

Проверка сгенерированного запроса:

[debug] QUERY ERROR source="stuff" db=0.3ms
SELECT ... FROM "stuff" AS c0 CROSS JOIN (jsonb_each(c0."stuff")) AS f1 WHERE (value->>'ref' = $1) ["ref_1"]

Вышеописанное работает, когда я убираю внешние скобки вокруг (jsonb_each(c0."stuff")).

Есть ли способ, чтобы фрагмент генерировал запрос без этих скобок, или мне нужно изменить дизайн запроса?

Спасибо

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Это ошибка в экто, исправлена ​​здесь https://github.com/elixir-ecto/ecto/issues/2537

0 голосов
/ 04 мая 2018

Кажется, что Ecto всегда заключает предложение в скобки, что обычно хорошо. Время, когда его нет, к сожалению, включает в себя определенные вызовы, такие как jsonb_each выше. Здесь есть вики для таких случаев: Правила скобок в PostgreSQL, есть ли краткое руководство?

В примере с исходным SQL-кодом был получен ответ с гораздо меньшим количеством голосов, который, как представляется, хорошо подходит как для выполнения этого запроса, так и для получения ожидаемой структуры.

sql = "SELECT * FROM "stuff" AS c0 CROSS JOIN jsonb_each(c0."stuff") AS f1 WHERE value->>'ref' = 'ref_1';"
result = JsonbTest.Repo.query!(sql)
Enum.map(result.rows, &JsonbTest.Repo.load(StuffStruct, {result.columns, &1}))
...