Не е необходимо да преоткривате колелото в PostgreSQL, има два внедрени прости метода за постигане на проверки за припокриване:
- SQL
OVERLAPS
оператор :
Достатъчно просто,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)
Това обаче позволява един диапазон да бъде точно след другия
(с други думи, той проверява начало <=време <край ).
Обикновено това също е просто. Но PostgreSQL няма вграден тип диапазон за time
(има обаче tsrange
, tstzrange
и daterange
за другите темпорални типове).
Трябва да създадете този тип диапазон за себе си:
CREATE TYPE timerange AS RANGE (subtype = time);
Но след това можете да проверите припокриването с
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)
Предимства на типовете обхват:
-
можете да контролирате себе си, как искате да се справите с границите на диапазон
е.пр. можете да използвате
timerange(start_at, end_at, '[]')
за да включи както началната, така и крайната точка на диапазоните. По подразбиране включва началото, но изключва крайната точка на диапазоните. -
може да се индексира, напр. с
CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
-
Ограничения за изключване :това по същество е същото, което искате да постигнете, но ще бъде наложено на ниво DB (като
UNIQUE
или всякакви други ограничения):ALTER TABLE events ADD CONSTRAINT events_exclude_overlapping EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);