fix(02): include all-day recurring masters in events route pre-filter
- Old filter: hasRrule=1 AND dtstartUtc < windowEnd All-day recurring masters have dtstartUtc=NULL so the comparison evaluates to NULL/false — 11 such rows in live cache were never returned - New filter: hasRrule=1 AND (dtstartUtc < windowEnd OR dtstartDate < end) The OR covers all-day masters whose only date column is dtstartDate (DATE) - expandOccurrences already does precise per-occurrence window checks, so over-selecting a master on the DATE path is safe - Extend events.test.ts: assert timed recurring master (dtstart 2024) returns occurrences in 2026 window; assert all-day recurring master (dtstartDate 2024, dtstartUtc NULL) returns its 2026-06-15 occurrence
This commit is contained in:
@@ -88,10 +88,17 @@ eventsRouter.get('/', zValidator('query', eventsQuerySchema), async (c) => {
|
||||
.innerJoin(users, eq(calendars.userId, users.id))
|
||||
.where(
|
||||
or(
|
||||
// Recurring masters: may have occurrences inside the window even if dtstartUtc is old
|
||||
// Recurring masters: may have occurrences inside the window even if dtstartUtc is old.
|
||||
// Two sub-cases:
|
||||
// (a) Timed recurring masters: dtstartUtc < windowEnd
|
||||
// (b) All-day recurring masters: dtstartUtc is NULL (DATE-only), use dtstartDate < end
|
||||
// A NULL dtstartUtc causes the timed comparison to be NULL/false, so (b) carries it.
|
||||
and(
|
||||
sql`${calendarEvents.hasRrule} = 1`,
|
||||
sql`${calendarEvents.dtstartUtc} < ${windowEndDate}`,
|
||||
or(
|
||||
sql`${calendarEvents.dtstartUtc} < ${windowEndDate}`,
|
||||
sql`${calendarEvents.dtstartDate} < ${end}`,
|
||||
),
|
||||
),
|
||||
// Non-recurring timed events: dtstartUtc falls in [windowStart, windowEnd)
|
||||
and(
|
||||
|
||||
Reference in New Issue
Block a user