Nie musisz wymyślać koła na nowo w PostgreSQL, istnieją dwie zaimplementowane proste metody uzyskania kontroli nakładania się:
- SQL
OVERLAPS
operator :
Wystarczająco proste,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)
Dzięki temu jeden zakres może być dokładnie po drugim
(innymi słowy, sprawdza start <=czas
To też jest zwykle proste. Ale PostgreSQL nie ma wbudowanego typu zakresu dla time
(jednak istnieją tsrange
, tstzrange
i daterange
dla innych typów czasowych).
Musisz stworzyć ten typ zakresu dla siebie:
CREATE TYPE timerange AS RANGE (subtype = time);
Ale potem możesz sprawdzić nakładanie się za pomocą
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)
Plusy typów zasięgu:
-
możesz kontrolować siebie, jak chcesz radzić sobie z granicami zasięgu
np. możesz użyć
timerange(start_at, end_at, '[]')
aby uwzględnić zarówno początek, jak i koniec zakresów. Domyślnie zawiera początek, ale wyklucza punkt końcowy zakresów. -
może być indeksowany, np. z
CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
-
Ograniczenia wykluczenia :jest to zasadniczo to samo, co chcesz osiągnąć, ale będzie to egzekwowane na poziomie bazy danych (np.
UNIQUE
lub inne ograniczenia):ALTER TABLE events ADD CONSTRAINT events_exclude_overlapping EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);