From d60f0735209dae1885afaa3d044581f67893a45e Mon Sep 17 00:00:00 2001 From: David Gorges Date: Fri, 30 Aug 2024 07:45:27 +0200 Subject: [PATCH 1/3] fix: query compatibility with postgresql MySQL is more relaxed than postgres when it comes to using aliases in having clauses. https://stackoverflow.com/questions/2068682/why-cant-i-use-alias-in-a-count-column-and-reference-it-in-a-having-clause explains the issue: The HAVING clause is evaluated before the SELECT - so the server doesn't yet know about that alias. --- src/Repository/EventTranslationRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Repository/EventTranslationRepository.php b/src/Repository/EventTranslationRepository.php index f3d8fd7..f6b82bb 100644 --- a/src/Repository/EventTranslationRepository.php +++ b/src/Repository/EventTranslationRepository.php @@ -29,7 +29,7 @@ public function findMissingLocaleByIds(array $ids, string $missingLocale, int $c $query = $this->createQueryBuilder('et') ->addCriteria($this->createIdsInCriteria($ids)) ->groupby('et.event') - ->having('eventCount < :countLocales') + ->having('COUNT(et.event) < :countLocales') ->setParameter('countLocales', $countLocales) ->andHaving('et.locale = :locale') ->setParameter('locale', $missingLocale) From cafca7eb3dd901c4b60eb6ac739bddac21ee9e4e Mon Sep 17 00:00:00 2001 From: David Gorges Date: Fri, 30 Aug 2024 07:49:27 +0200 Subject: [PATCH 2/3] fix: add event.locale to grouping for postgres compat --- src/Repository/EventTranslationRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Repository/EventTranslationRepository.php b/src/Repository/EventTranslationRepository.php index f6b82bb..66ecba6 100644 --- a/src/Repository/EventTranslationRepository.php +++ b/src/Repository/EventTranslationRepository.php @@ -28,7 +28,7 @@ public function findMissingLocaleByIds(array $ids, string $missingLocale, int $c { $query = $this->createQueryBuilder('et') ->addCriteria($this->createIdsInCriteria($ids)) - ->groupby('et.event') + ->groupBy('et.event, et.locale') ->having('COUNT(et.event) < :countLocales') ->setParameter('countLocales', $countLocales) ->andHaving('et.locale = :locale') From bf4e1e92267dc304fc6aec424c85639fdab44475 Mon Sep 17 00:00:00 2001 From: David Gorges Date: Fri, 30 Aug 2024 09:55:51 +0200 Subject: [PATCH 3/3] fix: get upcoming and active queries postgres compatibility --- src/Repository/EventRepository.php | 100 ++++++++++++++++++----------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/src/Repository/EventRepository.php b/src/Repository/EventRepository.php index 87673a2..7c89b4f 100644 --- a/src/Repository/EventRepository.php +++ b/src/Repository/EventRepository.php @@ -101,12 +101,24 @@ public static function createEnabledCriteria(): Criteria public function findAllScheduledEvents(int $limit) { - $query = $this->createQueryBuilder('e') - ->where('e.enabled = 1 AND (e.startDate >= :now OR (e.endDate IS NOT NULL AND e.endDate >= :now))') - ->orderBy("e.startDate", "ASC") + $now = new \DateTimeImmutable(); + $queryBuilder = $this->createQueryBuilder('e') + ->where('e.enabled = :enabled') + ->andWhere( + $queryBuilder->expr()->orX( + $queryBuilder->expr()->gte('e.startDate', ':now'), + $queryBuilder->expr()->andX( + $queryBuilder->expr()->isNotNull('e.endDate'), + $queryBuilder->expr()->gte('e.endDate', ':now') + ) + ) + ) + ->orderBy('e.startDate', 'ASC') ->setMaxResults($limit) - ->setParameter("now", (new \DateTimeImmutable())->format("Y-m-d")); - return $query->getQuery()->getResult(); + ->setParameter('enabled', 1) + ->setParameter('now', $now->format('Y-m-d')); + + return $queryBuilder->getQuery()->getResult(); } /** @@ -127,27 +139,27 @@ public function findAllScheduledEvents(int $limit) * @noinspection PhpMissingReturnTypeInspection * @noinspection PhpMissingParamTypeInspection */ -/* public function findByFilters( - $filters, - $page, - $pageSize, - $limit, - $locale, - $options = [], - ?UserInterface $user = null, - $entityClass = null, - $entityAlias = null, - $permission = null - ) { - $entities = $this->parentFindByFilters($filters, $page, $pageSize, $limit, $locale, $options); - - return \array_map( - function (Event $entity) use ($locale) { - return $entity->setLocale($locale); - }, - $entities - ); - }*/ + /* public function findByFilters( + $filters, + $page, + $pageSize, + $limit, + $locale, + $options = [], + ?UserInterface $user = null, + $entityClass = null, + $entityAlias = null, + $permission = null + ) { + $entities = $this->parentFindByFilters($filters, $page, $pageSize, $limit, $locale, $options); + + return \array_map( + function (Event $entity) use ($locale) { + return $entity->setLocale($locale); + }, + $entities + ); + }*/ protected function appendJoins(QueryBuilder $queryBuilder, $alias, $locale): void { @@ -166,9 +178,9 @@ protected function append(QueryBuilder $queryBuilder, string $alias, string $loc { $queryBuilder->andWhere($alias . '.enabled = true'); -/* $queryBuilder->andWhere('('. $alias .'.startDate >= :now OR ('. $alias .'.endDate IS NOT NULL AND '. $alias .'.endDate >= :now))'); - $queryBuilder->setParameter("now", (new Datetime())->format("Y-m-d H:i:s")); - $queryBuilder->orderBy($alias . ".startDate", "ASC");*/ + /* $queryBuilder->andWhere('('. $alias .'.startDate >= :now OR ('. $alias .'.endDate IS NOT NULL AND '. $alias .'.endDate >= :now))'); + $queryBuilder->setParameter("now", (new Datetime())->format("Y-m-d H:i:s")); + $queryBuilder->orderBy($alias . ".startDate", "ASC");*/ return []; } @@ -199,23 +211,33 @@ function (Event $entity) use ($locale) { public function getActiveEvents(array $filters, string $locale, ?int $page, $pageSize, $limit = null, array $options): array { - $pageCurrent = (key_exists('page', $options)) ? (int)$options['page'] : 0; + // Determine the current page + $pageCurrent = array_key_exists('page', $options) ? (int) $options['page'] : 0; + // Initialize the query builder $queryBuilder = $this->createQueryBuilder('event') ->leftJoin('event.translations', 'translation') - ->where('event.enabled = 1') - ->andWhere('translation.locale = :locale')->setParameter('locale', $locale) - ->orderBy('event.startDate', 'DESC') - ->setMaxResults($limit) - ->setFirstResult($pageCurrent * $limit); + ->where('event.enabled = :enabled') + ->andWhere('translation.locale = :locale') + ->setParameter('enabled', 1) + ->setParameter('locale', $locale) + ->orderBy('event.startDate', 'DESC'); + + // Apply limit and pagination + if ($limit !== null) { + $queryBuilder->setMaxResults($limit); + } + if ($pageCurrent !== null && $limit !== null) { + $queryBuilder->setFirstResult($pageCurrent * $limit); + } + // Apply additional filters $this->prepareFilter($queryBuilder, $filters); + // Execute the query and return results $events = $queryBuilder->getQuery()->getResult(); - if (!$events) { - return []; - } - return $events; + + return $events ?: []; } private function prepareFilter(QueryBuilder $queryBuilder, array $filters): void