11<?php
2+
3+ declare (strict_types=1 );
24/**
35 * @copyright Copyright (c) 2016, ownCloud, Inc.
46 *
3234use OCP \Activity \IManager ;
3335use OCP \DB \QueryBuilder \IQueryBuilder ;
3436use OCP \IDBConnection ;
37+ use Psr \Log \LoggerInterface ;
3538
3639/**
3740 * @brief Class for managing the data in the activities
@@ -48,14 +51,16 @@ class Data {
4851
4952 /** @var ?IQueryBuilder */
5053 protected $ insertMail ;
54+ private LoggerInterface $ logger ;
5155
5256 /**
5357 * @param IManager $activityManager
5458 * @param IDBConnection $connection
5559 */
56- public function __construct (IManager $ activityManager , IDBConnection $ connection ) {
60+ public function __construct (IManager $ activityManager , IDBConnection $ connection, LoggerInterface $ logger ) {
5761 $ this ->activityManager = $ activityManager ;
5862 $ this ->connection = $ connection ;
63+ $ this ->logger = $ logger ;
5964 }
6065
6166 /**
@@ -368,9 +373,16 @@ public function expire($expireDays = 365) {
368373 * 'field' => 'value' => `field` = 'value'
369374 * 'field' => array('value', 'operator') => `field` operator 'value'
370375 */
371- public function deleteActivities ($ conditions ) {
372- $ delete = $ this ->connection ->getQueryBuilder ();
373- $ delete ->delete ('activity ' );
376+ public function deleteActivities ($ conditions ): void {
377+ $ platform = $ this ->connection ->getDatabasePlatform ();
378+ if ($ platform instanceof MySQLPlatform) {
379+ $ this ->logger ->debug ('Choosing chunked activity delete for MySQL/MariaDB ' , ['app ' => 'activity ' ]);
380+ $ this ->deleteActivitiesForMySQL ($ conditions );
381+ return ;
382+ }
383+ $ this ->logger ->debug ('Choosing regular activity delete ' , ['app ' => 'activity ' ]);
384+ $ deleteQuery = $ this ->connection ->getQueryBuilder ();
385+ $ deleteQuery ->delete ('activity ' );
374386
375387 foreach ($ conditions as $ column => $ comparison ) {
376388 if (is_array ($ comparison )) {
@@ -381,22 +393,14 @@ public function deleteActivities($conditions) {
381393 $ value = $ comparison ;
382394 }
383395
384- $ delete ->andWhere ($ delete ->expr ()->comparison ($ column , $ operation , $ delete ->createNamedParameter ($ value )));
396+ $ deleteQuery ->andWhere ($ deleteQuery ->expr ()->comparison ($ column , $ operation , $ deleteQuery ->createNamedParameter ($ value )));
385397 }
386398
387- // Add galera safe delete chunking if using mysql
388- // Stops us hitting wsrep_max_ws_rows when large row counts are deleted
389- if ($ this ->connection ->getDatabasePlatform () instanceof MySQLPlatform) {
390- // Then use chunked delete
391- $ max = 100000 ;
392- $ delete ->setMaxResults ($ max );
393- do {
394- $ deleted = $ delete ->executeStatement ();
395- } while ($ deleted === $ max );
396- } else {
397- // Dont use chunked delete - let the DB handle the large row count natively
398- $ delete ->executeStatement ();
399- }
399+
400+
401+
402+ // Dont use chunked delete - let the DB handle the large row count natively
403+ $ deleteQuery ->executeStatement ();
400404 }
401405
402406 public function getById (int $ activityId ): ?IEvent {
@@ -467,4 +471,48 @@ public function getActivitySince(string $user, int $since, bool $byOthers) {
467471
468472 return $ query ->execute ()->fetch ();
469473 }
474+
475+ /**
476+ * Add galera safe delete chunking if using mysql
477+ * Stops us hitting wsrep_max_ws_rows when large row counts are deleted
478+ *
479+ * @param array $conditions
480+ * @return void
481+ */
482+ private function deleteActivitiesForMySQL (array $ conditions ): void {
483+ $ query = $ this ->connection ->getQueryBuilder ();
484+ $ query ->select ('activity_id ' )
485+ ->from ('activity ' );
486+
487+ foreach ($ conditions as $ column => $ comparison ) {
488+ if (is_array ($ comparison )) {
489+ $ operation = $ comparison [1 ] ?? '= ' ;
490+ $ value = $ comparison [0 ];
491+ } else {
492+ $ operation = '= ' ;
493+ $ value = $ comparison ;
494+ }
495+ $ query ->where ($ query ->expr ()->comparison ($ column , $ operation , $ query ->createNamedParameter ($ value )));
496+ }
497+
498+ $ query ->setMaxResults (10000 );
499+ $ result = $ query ->executeQuery ();
500+ $ count = $ result ->rowCount ();
501+ if ($ count === 0 ) {
502+ return ;
503+ }
504+ $ ids = array_map (static function (array $ id ) {
505+ return (int )$ id [0 ];
506+ }, $ result ->fetchAll (\PDO ::FETCH_NUM ));
507+ $ result ->closeCursor ();
508+
509+ $ deleteQuery = $ this ->connection ->getQueryBuilder ();
510+ $ deleteQuery ->delete ('activity ' );
511+ $ deleteQuery ->where ($ deleteQuery ->expr ()->in ('activity_id ' , $ deleteQuery ->createParameter ('ids ' ), IQueryBuilder::PARAM_INT_ARRAY ));
512+ $ deleteQuery ->setParameter ('ids ' , $ ids , IQueryBuilder::PARAM_INT_ARRAY );
513+ $ queryResult = $ deleteQuery ->executeStatement ();
514+ if ($ queryResult === 10000 ) {
515+ $ this ->deleteActivitiesForMySQL ($ conditions );
516+ }
517+ }
470518}
0 commit comments