From bbea4002d239e07d49c6296e4e374af0087360da Mon Sep 17 00:00:00 2001 From: Nicos Panayides Date: Tue, 14 Jan 2025 15:15:52 +0200 Subject: [PATCH 1/4] Improve performance on queries with skipAddTrashCondition. Move query scanning to a function to allow users to override/skip it based on their requirements. --- src/Model/Behavior/TrashBehavior.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Model/Behavior/TrashBehavior.php b/src/Model/Behavior/TrashBehavior.php index 6a58019..33411ce 100644 --- a/src/Model/Behavior/TrashBehavior.php +++ b/src/Model/Behavior/TrashBehavior.php @@ -180,7 +180,27 @@ public function trash(EntityInterface $entity, array $options = []): bool */ public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObject $options, bool $primary): void { + $option = $query->getOptions(); + if (empty($option['skipAddTrashCondition'])) { + return; + } + $field = $this->getTrashField(); + + if ($this->addTrashCondition($query, $field)) { + $query->andWhere($query->newExpr()->isNull($field)); + } + } + + /** + * Whether we need to add the trash condition to the query + * + * @param \Cake\ORM\Query\SelectQuery $query Query. + * @param string $field Trash field + * @return bool + */ + protected function addTrashCondition(SelectQuery $query, string $field): bool + { $addCondition = true; $query->traverseExpressions(function ($expression) use (&$addCondition, $field): void { @@ -205,11 +225,7 @@ public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObjec } }); - $option = $query->getOptions(); - - if ($addCondition && empty($option['skipAddTrashCondition'])) { - $query->andWhere($query->newExpr()->isNull($field)); - } + return $addCondition; } /** From 4e5a1883dad562b3f8ac6b5d165c22201ff42f6a Mon Sep 17 00:00:00 2001 From: Nicos Panayides Date: Tue, 14 Jan 2025 15:25:08 +0200 Subject: [PATCH 2/4] Fix the check for skipAddTrashCondition --- src/Model/Behavior/TrashBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/TrashBehavior.php b/src/Model/Behavior/TrashBehavior.php index 33411ce..fca4ebe 100644 --- a/src/Model/Behavior/TrashBehavior.php +++ b/src/Model/Behavior/TrashBehavior.php @@ -181,7 +181,7 @@ public function trash(EntityInterface $entity, array $options = []): bool public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObject $options, bool $primary): void { $option = $query->getOptions(); - if (empty($option['skipAddTrashCondition'])) { + if (!empty($option['skipAddTrashCondition'])) { return; } From 5646776b3c5614bbe8f88febb33d1fefc6df6bf6 Mon Sep 17 00:00:00 2001 From: Nicos Panayides Date: Tue, 14 Jan 2025 15:28:07 +0200 Subject: [PATCH 3/4] Rename function to make it clear what it does --- src/Model/Behavior/TrashBehavior.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/TrashBehavior.php b/src/Model/Behavior/TrashBehavior.php index fca4ebe..929c637 100644 --- a/src/Model/Behavior/TrashBehavior.php +++ b/src/Model/Behavior/TrashBehavior.php @@ -187,7 +187,7 @@ public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObjec $field = $this->getTrashField(); - if ($this->addTrashCondition($query, $field)) { + if ($this->shouldAddTrashCondition($query, $field)) { $query->andWhere($query->newExpr()->isNull($field)); } } @@ -199,7 +199,7 @@ public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObjec * @param string $field Trash field * @return bool */ - protected function addTrashCondition(SelectQuery $query, string $field): bool + protected function shouldAddTrashCondition(SelectQuery $query, string $field): bool { $addCondition = true; From 1b85a7677196c6ba8e6f104805fbc244c1767f5c Mon Sep 17 00:00:00 2001 From: Nicos Panayides Date: Mon, 3 Feb 2025 15:28:25 +0200 Subject: [PATCH 4/4] Fixes from PR and optimize findOnlyTrashed. Use options directly. Use field IS instead of express. --- src/Model/Behavior/TrashBehavior.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Model/Behavior/TrashBehavior.php b/src/Model/Behavior/TrashBehavior.php index 929c637..609983a 100644 --- a/src/Model/Behavior/TrashBehavior.php +++ b/src/Model/Behavior/TrashBehavior.php @@ -180,15 +180,14 @@ public function trash(EntityInterface $entity, array $options = []): bool */ public function beforeFind(EventInterface $event, SelectQuery $query, ArrayObject $options, bool $primary): void { - $option = $query->getOptions(); - if (!empty($option['skipAddTrashCondition'])) { + if (!empty($options['skipAddTrashCondition'])) { return; } $field = $this->getTrashField(); if ($this->shouldAddTrashCondition($query, $field)) { - $query->andWhere($query->newExpr()->isNull($field)); + $query->andWhere([$field . ' IS' => null]); } } @@ -237,7 +236,9 @@ protected function shouldAddTrashCondition(SelectQuery $query, string $field): b */ public function findOnlyTrashed(SelectQuery $query, array $options): SelectQuery { - return $query->andWhere($query->newExpr()->isNotNull($this->getTrashField())); + return $query + ->applyOptions(['skipAddTrashCondition' => true]) + ->andWhere($query->newExpr()->isNotNull($this->getTrashField())); } /**