No necesita reinventar la rueda en PostgreSQL, hay dos métodos simples implementados para lograr controles de superposición:
- SQL
OVERLAPS
operador :
Bastante simple,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)
Sin embargo, esto permite que un rango esté exactamente después del otro
(en otras palabras, verifica start <=time
Esto también es simple, por lo general. Pero PostgreSQL no tiene un tipo de rango incorporado para time
(sin embargo, hay tsrange
, tstzrange
y daterange
para los otros tipos temporales).
Necesitas crear este tipo de rango por ti mismo:
CREATE TYPE timerange AS RANGE (subtype = time);
Pero después de esto, puede verificar la superposición con
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)
Ventajas de los tipos de rango:
-
puedes controlarte a ti mismo, ¿cómo quieres manejar los límites del rango?
p.ej. podrías usar
timerange(start_at, end_at, '[]')
para incluir tanto el inicio como el punto final de los rangos. Por defecto incluye el inicio, pero excluye el punto final de los rangos. -
se puede indexar, p.ej. con
CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
-
Restricciones de exclusión :esto es esencialmente lo mismo, lo que desea lograr, pero se aplicará a nivel de base de datos (como,
UNIQUE
o cualquier otra restricción):ALTER TABLE events ADD CONSTRAINT events_exclude_overlapping EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);