From 25d29deba000be965888ef7781ef82130fa1912c Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Wed, 29 Jul 2026 09:03:50 +0200 Subject: [PATCH] calquery: fix $end/$finish typo that disabled the SQL end filter In the time-range condition assembly the branch selection tested $end, but the "end" attribute is stored in $finish ($finish = $v->GetAttribute("end")). $end was never assigned, so isset($end) was always false: a bounded time-range query (both start and end present) fell through to the "start only" branch and the SQL upper-bound predicate (first_instance_start <= :time_range_end, and the legacy dtstart < :time_range_end) was never emitted. The result stayed correct because a later PHP pass ($range_filter + expand_event_instances) re-applies the true range -- which is why this was invisible to the HTTP-level regression suite. But every bounded query therefore fetched all events whose series starts after the requested end, parsed each into a vComponent and ran recurrence expansion on it, only to discard it. Measured on a 6972-event database, a "today"/"this week" query fetched and expanded ~99 rows (~15%) more than necessary -- worst on exactly the narrow near-future windows clients poll most often. Test $finish so the end predicate is emitted for bounded queries. Output is unchanged (the existing regression suite still passes); this only lets PostgreSQL prune events that start after the window instead of dropping them in PHP. Co-Authored-By: Claude Opus 4.8 --- inc/caldav-REPORT-calquery.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/caldav-REPORT-calquery.php b/inc/caldav-REPORT-calquery.php index c0ec60a9..e7d8ea59 100644 --- a/inc/caldav-REPORT-calquery.php +++ b/inc/caldav-REPORT-calquery.php @@ -232,16 +232,16 @@ function SqlFilterFragment( $filter, $components, $property = null, $parameter = $new_start_cond = "last_instance_end IS NULL OR last_instance_end >= :time_range_start"; $new_end_cond = "first_instance_start <= :time_range_end"; - if (!isset($start) && !isset($end)) { + if (!isset($start) && !isset($finish)) { $legacy_cond = "true"; $new_cond = "true"; - } else if (!isset($start) && isset($end)) { + } else if (!isset($start) && isset($finish)) { $legacy_cond = $legacy_end_cond; $new_cond = $new_end_cond; - } else if (isset($start) && !isset($end)) { + } else if (isset($start) && !isset($finish)) { $legacy_cond = $legacy_start_cond; $new_cond = $new_start_cond; - } else if (isset($start) && isset($end)) { + } else if (isset($start) && isset($finish)) { $legacy_cond = "($legacy_end_cond) AND ($legacy_start_cond)"; $new_cond = "($new_end_cond) AND ($new_start_cond)"; }