From c27b02512f36ac8e90267f9e95e58f839bfc1b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 5 Mar 2023 00:57:01 +0100 Subject: [PATCH] Fixed problem with part tables that the wrong number of parts (and therefore pages) were displayed. This hopefully does not break anything else. --- .../Adapters/CustomFetchJoinORMAdapter.php | 54 +++++++++++++++++++ src/DataTables/PartsDataTable.php | 3 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/DataTables/Adapters/CustomFetchJoinORMAdapter.php diff --git a/src/DataTables/Adapters/CustomFetchJoinORMAdapter.php b/src/DataTables/Adapters/CustomFetchJoinORMAdapter.php new file mode 100644 index 00000000..052e2e28 --- /dev/null +++ b/src/DataTables/Adapters/CustomFetchJoinORMAdapter.php @@ -0,0 +1,54 @@ +. + */ + +namespace App\DataTables\Adapters; + +use Doctrine\ORM\Query; +use Doctrine\ORM\QueryBuilder; +use Doctrine\ORM\Tools\Pagination\Paginator; +use Omines\DataTablesBundle\Adapter\Doctrine\FetchJoinORMAdapter; + +/** + * This class is a workaround for a bug (or edge case behavior) in the FetchJoinORMAdapter or better the used Paginator + * and CountOutputWalker. + * If the query contains multiple GROUP BY clauses, the result of the count query is wrong, as some lines are counted + * multiple times. This is because the CountOutputWalker does not use DISTINCT in the count query, if it contains a GROUP BY. + * + * We work around this by removing the GROUP BY clause from the query, and only adding the first root alias as GROUP BY (the part table). + * This way we get the correct count, without breaking the query (we need a GROUP BY for the HAVING clauses). + * + * As a side effect this also seems to improve the performance of the count query a bit (which makes up a lot of the total query time). + */ +class CustomFetchJoinORMAdapter extends FetchJoinORMAdapter +{ + public function getCount(QueryBuilder $queryBuilder, $identifier) + { + $qb_without_group_by = clone $queryBuilder; + + //Remove the groupBy clause from the query for the count + //And add the root alias as group by, so we can use HAVING clauses + $qb_without_group_by->resetDQLPart('groupBy'); + $qb_without_group_by->addGroupBy($queryBuilder->getRootAliases()[0]); + + $paginator = new Paginator($qb_without_group_by); + + return $paginator->count(); + } +} \ No newline at end of file diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index d67ed0db..beb050bd 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\DataTables; +use App\DataTables\Adapters\CustomFetchJoinORMAdapter; use App\DataTables\Column\EntityColumn; use App\DataTables\Column\IconLinkColumn; use App\DataTables\Column\LocaleDateTimeColumn; @@ -281,7 +282,7 @@ final class PartsDataTable implements DataTableTypeInterface ]) ->addOrderBy('name') - ->createAdapter(FetchJoinORMAdapter::class, [ + ->createAdapter(CustomFetchJoinORMAdapter::class, [ 'simple_total_query' => true, 'query' => function (QueryBuilder $builder): void { $this->getQuery($builder);