Only add the amountSum select for part tables if it is really required

This commit is contained in:
Jan Böhmer 2024-02-29 23:35:05 +01:00
parent c635637c00
commit a72a61091a
2 changed files with 21 additions and 10 deletions

View file

@ -135,6 +135,10 @@ class TwoStepORMAdapter extends ORMAdapter
protected function getCount(QueryBuilder $queryBuilder, $identifier): int protected function getCount(QueryBuilder $queryBuilder, $identifier): int
{ {
if ($this->query_modifier !== null) {
$queryBuilder = $this->query_modifier->__invoke(clone $queryBuilder);
}
//Check if the queryBuilder is having a HAVING clause, which would make the count query invalid //Check if the queryBuilder is having a HAVING clause, which would make the count query invalid
if (empty($queryBuilder->getDQLPart('having'))) { if (empty($queryBuilder->getDQLPart('having'))) {
//If not, we can use the simple count query //If not, we can use the simple count query

View file

@ -231,20 +231,13 @@ final class PartsDataTable implements DataTableTypeInterface
/* In the filter query we only select the IDs. The fetching of the full entities is done in the detail query. /* In the filter query we only select the IDs. The fetching of the full entities is done in the detail query.
* We only need to join the entities here, so we can filter by them. * We only need to join the entities here, so we can filter by them.
* The filter conditions are added to this QB in the buildCriteria method. * The filter conditions are added to this QB in the buildCriteria method.
*
* The amountSum field and the joins are dynmically added by the addJoins method, if the fields are used in the query.
* This improves the performance, as we do not need to join all tables, if we do not need them.
*/ */
$builder $builder
->select('part.id') ->select('part.id')
->addSelect('part.minamount AS HIDDEN minamount') ->addSelect('part.minamount AS HIDDEN minamount')
//Calculate amount sum using a subquery, so we can filter and sort by it
->addSelect(
'(
SELECT IFNULL(SUM(partLot.amount), 0.0)
FROM '.PartLot::class.' partLot
WHERE partLot.part = part.id
AND partLot.instock_unknown = false
AND (partLot.expiration_date IS NULL OR partLot.expiration_date > CURRENT_DATE())
) AS HIDDEN amountSum'
)
->from(Part::class, 'part') ->from(Part::class, 'part')
//This must be the only group by, or the paginator will not work correctly //This must be the only group by, or the paginator will not work correctly
@ -323,6 +316,20 @@ final class PartsDataTable implements DataTableTypeInterface
//The join fields get prefixed with an underscore, so we can check if they are used in the query easy without confusing them for a part subfield //The join fields get prefixed with an underscore, so we can check if they are used in the query easy without confusing them for a part subfield
$dql = $builder->getDQL(); $dql = $builder->getDQL();
//Add the amountSum field, if it is used in the query
if (str_contains($dql, 'amountSum')) {
//Calculate amount sum using a subquery, so we can filter and sort by it
$builder->addSelect(
'(
SELECT IFNULL(SUM(partLot.amount), 0.0)
FROM '.PartLot::class.' partLot
WHERE partLot.part = part.id
AND partLot.instock_unknown = false
AND (partLot.expiration_date IS NULL OR partLot.expiration_date > CURRENT_DATE())
) AS HIDDEN amountSum'
);
}
if (str_contains($dql, '_category')) { if (str_contains($dql, '_category')) {
$builder->leftJoin('part.category', '_category'); $builder->leftJoin('part.category', '_category');
} }