Таблица Ареля с использованием метода OVERLAPS в PostgreSQL - PullRequest
0 голосов
/ 14 сентября 2018

Позвольте мне предвосхитить это, признав, что есть несколько различных способов достижения перекрытия, но в отношении этого вопроса я специально пытаюсь выяснить, как использовать фактический метод PostgreSQL OVERLAPS с Arel. С этой целью этот вопрос больше связан с получением лучшего понимания Arel, а не с реализацией некоторой версии перекрывающихся функций.

Я использую Rails 5.1

Это оператор SQL, который я пытаюсь продублировать в Arel:

SELECT DISTINCT
  venues.id
FROM
  venues
LEFT OUTER JOIN
  reservations
ON
  venues.id = reservations.venue_id
WHERE (
  (reservations.venue_id IS NULL)
  OR NOT (
    (reservations.start, reservations.end)
    OVERLAPS
    (DATE '2018-09-02', DATE '2018-09-03')
  )
)

В настоящее время у меня есть следующее, которое генерирует вышеупомянутое:

Venue.arel_table.project(
  Venue.arel_table[:id]
).from(
  Venue.arel_table
).join(
  Reservation.arel_table, Arel::Nodes::OuterJoin
).on(
  Venue.arel_table[:id].eq(Reservation.arel_table[:venue_id])
).where(
 Arel::Nodes::Grouping.new(
    Reservation.arel_table[:venue_id].eq(nil)
  ).or(
    Arel.sql("NOT ((reservations.start, reservations.end) OVERLAPS (DATE '2018-09-02', DATE '2018-09-03'))")
  )
)

Однако я чувствую, что, возможно, есть лучший способ сделать это; Я пытался реализовать Arel::Nodes::NamedFunction для OVERLAPS, однако, когда я заменяю вышеприведенный оператор Arel.sql на следующий, он не выполняет SQL должным образом:

Arel::Nodes::NamedFunction.new(
  'OVERLAPS',
  [
    Arel::Nodes::SqlLiteral.new('(reservations.start, reservations.end)'),
    Arel::Nodes::SqlLiteral.new("(DATE '2018-09-02', DATE '2018-09-03')")
  ]
) 

приводит к

...OVERLAPS ((reservations.start, reservations.end), (DATE '2018-09-02', DATE '2018-09-03'))

Как правильно реализовать OVERLAPS с Arel?

1 Ответ

0 голосов
/ 24 сентября 2018

Поскольку OVERLAPS является оператором SQL, я считаю, что должно работать следующее выражение:

Arel::Nodes::InfixOperation.new(
  'OVERLAPS', 
  Arel::Nodes::SqlLiteral.new('(reservations.start, reservations.end)'),
  Arel::Nodes::SqlLiteral.new("(DATE '2018-09-02', DATE '2018-09-03')"
)
...