From e3b5c331be4a4525e5728ffe336c628b59eb33fb Mon Sep 17 00:00:00 2001 From: Andrew Ruthven Date: Sat, 4 Feb 2023 21:22:57 +1300 Subject: [PATCH] Add a primary key to calendar_alarm table. Also fixed a bug in scripts/refresh-alarms.php if there was an alarm with a duplicate trigger. This is part of the fix for #276. --- dba/davical.sql | 4 +++- dba/patches/1.3.4.sql | 10 ++++++++++ inc/WritableCollection.php | 6 ++++-- inc/caldav-PUT-functions.php | 6 ++++-- scripts/refresh-alarms.php | 8 ++++---- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/dba/davical.sql b/dba/davical.sql index a58b9d91..73048b8d 100644 --- a/dba/davical.sql +++ b/dba/davical.sql @@ -403,13 +403,15 @@ CREATE TABLE addressbook_address_email ( CREATE TABLE calendar_alarm ( dav_id INT8 NOT NULL REFERENCES caldav_data(dav_id) ON UPDATE CASCADE ON DELETE CASCADE, + count INT, action TEXT, trigger TEXT, summary TEXT, description TEXT, next_trigger TIMESTAMP WITH TIME ZONE, component TEXT, -- The full text of the component - trigger_state CHAR DEFAULT 'N' -- 'N' => 'New/Needs setting', 'A' = 'Active', 'O' = 'Old' + trigger_state CHAR DEFAULT 'N', -- 'N' => 'New/Needs setting', 'A' = 'Active', 'O' = 'Old' + UNIQUE (dav_id, count) ); diff --git a/dba/patches/1.3.4.sql b/dba/patches/1.3.4.sql index aa8a32a1..e2eb2a2b 100644 --- a/dba/patches/1.3.4.sql +++ b/dba/patches/1.3.4.sql @@ -41,6 +41,16 @@ UPDATE addressbook_address_tel CREATE UNIQUE INDEX addressbook_address_tel_pk ON addressbook_address_tel(dav_id, count); +-- calendar_alarm +ALTER TABLE calendar_alarm + ADD COLUMN count INT; + +UPDATE calendar_alarm + SET count = nextval('temporary_seq'); + +CREATE UNIQUE INDEX calendar_alarms_pk + ON calendar_alarm(dav_id, count); + -- Tidy up after ourselves. DROP SEQUENCE temporary_seq; diff --git a/inc/WritableCollection.php b/inc/WritableCollection.php index 112b073a..6ddae80d 100644 --- a/inc/WritableCollection.php +++ b/inc/WritableCollection.php @@ -326,10 +326,11 @@ EOSQL; $components = $vcal->GetComponents(); - $qry->SetSql('INSERT INTO calendar_alarm ( dav_id, action, trigger, summary, description, component, next_trigger ) - VALUES( '.$dav_id.', :action, :trigger, :summary, :description, :component, + $qry->SetSql('INSERT INTO calendar_alarm ( dav_id, count, action, trigger, summary, description, component, next_trigger ) + VALUES( '.$dav_id.', :count, :action, :trigger, :summary, :description, :component, :related::timestamp with time zone + :related_trigger::interval )' ); $qry->Prepare(); + $count = 0; foreach( $components AS $component ) { if ( $component->GetType() == 'VTIMEZONE' ) continue; $alarms = $component->GetComponents('VALARM'); @@ -370,6 +371,7 @@ EOSQL; $qry->Bind(':component', $v->Render()); $qry->Bind(':related', $related ); $qry->Bind(':related_trigger', $related_trigger ); + $qry->Bind(':count', $count++ ); $qry->Exec('PUT',__LINE__,__FILE__); } } diff --git a/inc/caldav-PUT-functions.php b/inc/caldav-PUT-functions.php index 4be240a3..d7a3b051 100644 --- a/inc/caldav-PUT-functions.php +++ b/inc/caldav-PUT-functions.php @@ -1270,10 +1270,11 @@ function write_alarms( $dav_id, vComponent $ical ) { $alarms = $ical->GetComponents('VALARM'); if ( count($alarms) < 1 ) return; - $qry->SetSql('INSERT INTO calendar_alarm ( dav_id, action, trigger, summary, description, component, next_trigger ) - VALUES( '.$dav_id.', :action, :trigger, :summary, :description, :component, + $qry->SetSql('INSERT INTO calendar_alarm ( dav_id, count, action, trigger, summary, description, component, next_trigger ) + VALUES( '.$dav_id.', :count, :action, :trigger, :summary, :description, :component, :related::timestamp with time zone + :related_trigger::interval )' ); $qry->Prepare(); + $count = 0; foreach( $alarms AS $v ) { $trigger = array_merge($v->GetProperties('TRIGGER')); if ( $trigger == null ) continue; // Bogus data. @@ -1314,6 +1315,7 @@ function write_alarms( $dav_id, vComponent $ical ) { $qry->Bind(':component', $v->Render()); $qry->Bind(':related', $related_date->UTC() ); $qry->Bind(':related_trigger', $related_trigger ); + $qry->Bind(':count', $count++ ); $qry->Exec('PUT',__LINE__,__FILE__); } } diff --git a/scripts/refresh-alarms.php b/scripts/refresh-alarms.php index 78cf4c8c..252ce7f3 100755 --- a/scripts/refresh-alarms.php +++ b/scripts/refresh-alarms.php @@ -165,14 +165,14 @@ if ( $qry->Exec() && $qry->rows() ) { if ( isset($next) && $next < $expand_range_end ) { if ( $args->debug ) printf( "refresh: Found next alarm instance on '%s'\n", $next->UTC() ); - $sql = 'UPDATE calendar_alarm SET next_trigger = :next WHERE dav_id = :id AND component = :component'; - $update = new AwlQuery( $sql, array( ':next' => $next->UTC(), ':id' => $alarm->dav_id, ':component' => $alarm->component ) ); + $sql = 'UPDATE calendar_alarm SET next_trigger = :next WHERE dav_id = :id AND count = :count AND component = :component'; + $update = new AwlQuery( $sql, array( ':next' => $next->UTC(), ':id' => $alarm->dav_id, ':count' => $alarm->count, ':component' => $alarm->component ) ); $update->Exec('refresh-alarms', __LINE__, __FILE__ ); } else if ( $args->set_last && isset($last) && $last < $earliest ) { if ( $args->debug ) printf( "refresh: Found past final alarm instance on '%s'\n", $last->UTC() ); - $sql = 'UPDATE calendar_alarm SET next_trigger = :last WHERE dav_id = :id AND component = :component'; - $update = new AwlQuery( $sql, array( ':last' => $last->UTC(), ':id' => $alarm->dav_id, ':component' => $alarm->component ) ); + $sql = 'UPDATE calendar_alarm SET next_trigger = :last WHERE dav_id = :id AND count = :count AND component = :component'; + $update = new AwlQuery( $sql, array( ':last' => $last->UTC(), ':id' => $alarm->dav_id, ':count' => $alarm->count, ':component' => $alarm->component ) ); $update->Exec('refresh-alarms', __LINE__, __FILE__ ); } else if ( $args->debug && isset($next) && $next < $expand_range_end ) {