From ffbf65b387c81d352ce7860bd665654d3f06a520 Mon Sep 17 00:00:00 2001 From: Hamza Date: Wed, 8 Jul 2026 15:11:42 +0200 Subject: [PATCH] test(dav): fix ORA-00932: inconsistent datatypes: expected - got BLOB Signed-off-by: Hamza --- apps/dav/lib/CalDAV/Reminder/Backend.php | 25 +++- .../unit/CalDAV/Reminder/BackendTest.php | 114 ++++++++++++------ apps/user_status/lib/Db/UserStatusMapper.php | 3 +- 3 files changed, 100 insertions(+), 42 deletions(-) diff --git a/apps/dav/lib/CalDAV/Reminder/Backend.php b/apps/dav/lib/CalDAV/Reminder/Backend.php index 5ea4566fa4c36..f35395d312b87 100644 --- a/apps/dav/lib/CalDAV/Reminder/Backend.php +++ b/apps/dav/lib/CalDAV/Reminder/Backend.php @@ -43,13 +43,12 @@ public function getRemindersToProcess():array { ->from('calendar_reminders', 'cr') ->where($query->expr()->lte('cr.notification_date', $query->createNamedParameter($this->timeFactory->getTime()))) ->join('cr', 'calendarobjects', 'co', $query->expr()->eq('cr.object_id', 'co.id')) - ->join('cr', 'calendars', 'c', $query->expr()->eq('cr.calendar_id', 'c.id')) - ->groupBy('cr.event_hash', 'cr.notification_date', 'cr.type', 'cr.id', 'cr.calendar_id', 'cr.object_id', 'cr.is_recurring', 'cr.uid', 'cr.recurrence_id', 'cr.is_recurrence_exception', 'cr.alarm_hash', 'cr.is_relative', 'cr.is_repeat_based', 'co.calendardata', 'c.displayname', 'c.principaluri'); + ->join('cr', 'calendars', 'c', $query->expr()->eq('cr.calendar_id', 'c.id')); $stmt = $query->executeQuery(); return array_map( [$this, 'fixRowTyping'], - $stmt->fetchAllAssociative() + $this->deduplicateReminderRows($stmt->fetchAllAssociative()) ); } @@ -178,6 +177,26 @@ public function cleanRemindersForCalendar(int $calendarId):void { ->executeStatement(); } + /** + * @param array> $rows + * @return array> + */ + private function deduplicateReminderRows(array $rows): array { + $uniqueRows = []; + foreach ($rows as $row) { + $key = implode("\0", [ + (string)$row['notification_date'], + (string)$row['event_hash'], + (string)$row['type'], + ]); + if (!isset($uniqueRows[$key])) { + $uniqueRows[$key] = $row; + } + } + + return array_values($uniqueRows); + } + /** * @param array $row * @return array diff --git a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php index d92e827092aac..1b835882251ab 100644 --- a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php +++ b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php @@ -53,7 +53,7 @@ public function testCleanRemindersForEvent(): void { ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(4, $rows); + $this->assertCount(5, $rows); $this->reminderBackend->cleanRemindersForEvent(1); @@ -73,7 +73,7 @@ public function testCleanRemindersForCalendar(): void { ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(4, $rows); + $this->assertCount(5, $rows); $this->reminderBackend->cleanRemindersForCalendar(1); @@ -93,7 +93,7 @@ public function testRemoveReminder(): void { ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(4, $rows); + $this->assertCount(5, $rows); $this->reminderBackend->removeReminder((int)$rows[3]['id']); @@ -103,7 +103,7 @@ public function testRemoveReminder(): void { ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(3, $rows); + $this->assertCount(4, $rows); } public function testGetRemindersToProcess(): void { @@ -163,37 +163,54 @@ public function testGetRemindersToProcess(): void { public function testGetAllScheduledRemindersForEvent(): void { $rows = $this->reminderBackend->getAllScheduledRemindersForEvent(1); - $this->assertCount(2, $rows); + $this->assertCount(3, $rows); unset($rows[0]['id']); unset($rows[1]['id']); - - $this->assertEquals($rows[0], [ - 'calendar_id' => 1, - 'object_id' => 1, - 'uid' => 'asd', - 'is_recurring' => false, - 'recurrence_id' => 123458, - 'is_recurrence_exception' => false, - 'event_hash' => 'asd123', - 'alarm_hash' => 'asd567', - 'type' => 'EMAIL', - 'is_relative' => true, - 'notification_date' => 123456, - 'is_repeat_based' => false, - ]); - $this->assertEquals($rows[1], [ - 'calendar_id' => 1, - 'object_id' => 1, - 'uid' => 'asd', - 'is_recurring' => false, - 'recurrence_id' => 123458, - 'is_recurrence_exception' => false, - 'event_hash' => 'asd123', - 'alarm_hash' => 'asd567', - 'type' => 'AUDIO', - 'is_relative' => true, - 'notification_date' => 123456, - 'is_repeat_based' => false, + unset($rows[2]['id']); + + $this->assertEqualsCanonicalizing($rows, [ + [ + 'calendar_id' => 1, + 'object_id' => 1, + 'uid' => 'asd', + 'is_recurring' => false, + 'recurrence_id' => 123458, + 'is_recurrence_exception' => false, + 'event_hash' => 'asd123', + 'alarm_hash' => 'asd567', + 'type' => 'EMAIL', + 'is_relative' => true, + 'notification_date' => 123456, + 'is_repeat_based' => false, + ], + [ + 'calendar_id' => 1, + 'object_id' => 1, + 'uid' => 'asd', + 'is_recurring' => false, + 'recurrence_id' => 123458, + 'is_recurrence_exception' => false, + 'event_hash' => 'asd123', + 'alarm_hash' => 'asd567', + 'type' => 'AUDIO', + 'is_relative' => true, + 'notification_date' => 123456, + 'is_repeat_based' => false, + ], + [ + 'calendar_id' => 1, + 'object_id' => 1, + 'uid' => 'asd', + 'is_recurring' => false, + 'recurrence_id' => 123458, + 'is_recurrence_exception' => false, + 'event_hash' => 'asd123', + 'alarm_hash' => 'duplicate', + 'type' => 'EMAIL', + 'is_relative' => true, + 'notification_date' => 123456, + 'is_repeat_based' => false, + ], ]); } @@ -204,7 +221,7 @@ public function testInsertReminder(): void { ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(4, $rows); + $this->assertCount(5, $rows); $this->reminderBackend->insertReminder(42, 1337, 'uid99', true, 12345678, true, 'hash99', 'hash42', 'AUDIO', false, 12345670, false); @@ -212,14 +229,15 @@ public function testInsertReminder(): void { $query = Server::get(IDBConnection::class)->getQueryBuilder(); $rows = $query->select('*') ->from('calendar_reminders') + ->orderBy('id') ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(5, $rows); + $this->assertCount(6, $rows); - unset($rows[4]['id']); + unset($rows[5]['id']); - $this->assertEquals($rows[4], [ + $this->assertEquals($rows[5], [ 'calendar_id' => '42', 'object_id' => '1337', 'is_recurring' => '1', @@ -239,10 +257,11 @@ public function testUpdateReminder(): void { $query = Server::get(IDBConnection::class)->getQueryBuilder(); $rows = $query->select('*') ->from('calendar_reminders') + ->orderBy('id') ->executeQuery() ->fetchAllAssociative(); - $this->assertCount(4, $rows); + $this->assertCount(5, $rows); $this->assertEquals($rows[3]['notification_date'], 123600); @@ -387,5 +406,24 @@ private function createRemindersTestSet(): void { 'is_repeat_based' => $query->createNamedParameter(0), ]) ->executeStatement(); + + // add a duplicate to test getRemindersToProcess dedup + $query = Server::get(IDBConnection::class)->getQueryBuilder(); + $query->insert('calendar_reminders') + ->values([ + 'calendar_id' => $query->createNamedParameter(1), + 'object_id' => $query->createNamedParameter(1), + 'uid' => $query->createNamedParameter('asd'), + 'is_recurring' => $query->createNamedParameter(0), + 'recurrence_id' => $query->createNamedParameter(123458), + 'is_recurrence_exception' => $query->createNamedParameter(0), + 'event_hash' => $query->createNamedParameter('asd123'), + 'alarm_hash' => $query->createNamedParameter('duplicate'), + 'type' => $query->createNamedParameter('EMAIL'), + 'is_relative' => $query->createNamedParameter(1), + 'notification_date' => $query->createNamedParameter(123456), + 'is_repeat_based' => $query->createNamedParameter(0), + ]) + ->executeStatement(); } } diff --git a/apps/user_status/lib/Db/UserStatusMapper.php b/apps/user_status/lib/Db/UserStatusMapper.php index ea3b76c8e564d..13bf94754ef03 100644 --- a/apps/user_status/lib/Db/UserStatusMapper.php +++ b/apps/user_status/lib/Db/UserStatusMapper.php @@ -37,7 +37,8 @@ public function findAll(?int $limit = null, ?int $offset = null):array { $qb ->select('*') ->from($this->tableName) - ->where($qb->expr()->eq('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))); + ->where($qb->expr()->eq('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))) + ->orderBy('user_id', 'ASC'); if ($limit !== null) { $qb->setMaxResults($limit);