PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como validar tempos sobrepostos no Rails com postgresql


Você não precisa reinventar a roda no PostgreSQL, existem dois métodos simples implementados para realizar verificações de sobreposição:
  1. SQL's OVERLAPS operador :

Simples o suficiente,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)

No entanto, isso permite que um intervalo seja exatamente após o outro
(em outras palavras, ele verifica início <=tempo ).
  1. Tipos de intervalo' && operador (sobreposições) :

Isso também é simples, geralmente. Mas o PostgreSQL não tem um tipo de intervalo embutido para time (no entanto, existem tsrange , tstzrange e daterange para os outros tipos temporais).

Você precisa criar este tipo de intervalo para si mesmo:
CREATE TYPE timerange AS RANGE (subtype = time);

Mas depois disso, você pode verificar a sobreposição com
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)

Prós dos tipos de intervalo:

  • você pode se controlar, como você deseja lidar com os limites do intervalo

    f.ex. você pode usar timerange(start_at, end_at, '[]') para incluir o ponto inicial e o ponto final dos intervalos. Por padrão, inclui o início, mas exclui o ponto final dos intervalos.

  • pode ser indexado, f.ex. com
    CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
    

  • Restrições de exclusão :isso é essencialmente o mesmo, o que você deseja alcançar, mas será aplicado no nível do banco de dados (como, UNIQUE ou quaisquer outras restrições):
    ALTER TABLE events
      ADD CONSTRAINT events_exclude_overlapping
      EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);