Skip to content

Commit 940f786

Browse files
authored
Merge pull request #698 from nextras/fix-lifting
Fix having lifting required by row aggregator
2 parents ec754d4 + 9bb40ad commit 940f786

8 files changed

Lines changed: 115 additions & 5 deletions

File tree

src/Collection/Aggregations/Aggregator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,7 @@ public function aggregateExpression(
3434
DbalExpressionResult $expression,
3535
ExpressionContext $context,
3636
): DbalExpressionResult;
37+
38+
39+
public function isHavingClauseRequired(): bool;
3740
}

src/Collection/Aggregations/AnyAggregator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Nextras\Orm\Collection\Aggregations;
44

55

6-
use Nextras\Dbal\QueryBuilder\QueryBuilder;
76
use Nextras\Orm\Collection\Expression\ExpressionContext;
87
use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult;
98
use Nextras\Orm\Collection\Functions\Result\DbalTableJoin;
@@ -86,4 +85,10 @@ public function aggregateExpression(
8685
havingArgs: [$join->toPrimaryKey],
8786
);
8887
}
88+
89+
90+
public function isHavingClauseRequired(): bool
91+
{
92+
return false;
93+
}
8994
}

src/Collection/Aggregations/CountAggregator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Nextras\Orm\Collection\Aggregations;
44

55

6-
use Nextras\Dbal\QueryBuilder\QueryBuilder;
76
use Nextras\Orm\Collection\Expression\ExpressionContext;
87
use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult;
98
use Nextras\Orm\Collection\Functions\Result\DbalTableJoin;
@@ -113,4 +112,10 @@ public function aggregateExpression(
113112
);
114113
}
115114
}
115+
116+
117+
public function isHavingClauseRequired(): bool
118+
{
119+
return true;
120+
}
116121
}

src/Collection/Aggregations/NoneAggregator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Nextras\Orm\Collection\Aggregations;
44

55

6-
use Nextras\Dbal\QueryBuilder\QueryBuilder;
76
use Nextras\Orm\Collection\Expression\ExpressionContext;
87
use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult;
98
use Nextras\Orm\Collection\Functions\Result\DbalTableJoin;
@@ -80,4 +79,10 @@ public function aggregateExpression(
8079
havingArgs: [$join->toPrimaryKey],
8180
);
8281
}
82+
83+
84+
public function isHavingClauseRequired(): bool
85+
{
86+
return true;
87+
}
8388
}

src/Collection/Aggregations/NumericAggregator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Nextras\Orm\Collection\Aggregations;
44

55

6-
use Nextras\Dbal\QueryBuilder\QueryBuilder;
76
use Nextras\Orm\Collection\Expression\ExpressionContext;
87
use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult;
98

@@ -53,4 +52,10 @@ public function aggregateExpression(
5352
havingArgs: $expression->args,
5453
);
5554
}
55+
56+
57+
public function isHavingClauseRequired(): bool
58+
{
59+
return true;
60+
}
5661
}

src/Collection/Functions/JunctionFunctionTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ protected function processQueryBuilderExpressionWithModifier(
7474
$expressions = [];
7575
foreach ($normalized as $collectionFunctionArgs) {
7676
$expressions[] = $expression = $helper->processExpression($builder, $collectionFunctionArgs, $aggregator);
77-
if ($expression->havingExpression !== null) {
77+
if ($expression->havingExpression !== null || ($expression->aggregator?->isHavingClauseRequired() ?? false)) {
7878
$requiresHaving = true;
7979
}
8080
}

tests/cases/integration/Collection/collection.aggregation.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace NextrasTests\Orm\Integration\Collection;
99

1010

11+
use Nextras\Orm\Collection\Aggregations\NoneAggregator;
1112
use Nextras\Orm\Collection\Functions\AvgAggregateFunction;
1213
use Nextras\Orm\Collection\Functions\CompareGreaterThanEqualsFunction;
1314
use Nextras\Orm\Collection\Functions\CompareGreaterThanFunction;
@@ -214,6 +215,31 @@ class CollectionAggregationTest extends DataTestCase
214215
]);
215216
Assert::same(3, $books->count()); // book #1, #2, #3
216217
}
218+
219+
220+
public function testRowAggregatorImposingLifting(): void
221+
{
222+
$books = $this->orm->books->findBy([
223+
ICollection::OR,
224+
['title' => 'Book 1'], // book #1
225+
[ICollection::AND, new NoneAggregator(), 'tags->id' => 2], // book #3, #4
226+
]);
227+
Assert::same(3, $books->count());
228+
229+
$books = $this->orm->books->findBy([
230+
ICollection::AND,
231+
['title' => 'Book 1'], // book #1
232+
[ICollection::AND, new NoneAggregator(), 'tags->id' => 2], // book #3, #4
233+
]);
234+
Assert::same(0, $books->count());
235+
236+
$books = $this->orm->books->findBy([
237+
ICollection::AND,
238+
['title' => 'Book 1'], // book #1
239+
[ICollection::AND, new NoneAggregator(), 'tags->id' => 3], // book #1, #4
240+
]);
241+
Assert::same(1, $books->count());
242+
}
217243
}
218244

219245

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
SELECT
2+
"books".*
3+
FROM
4+
"books" AS "books"
5+
LEFT JOIN "books_x_tags" AS "books_x_tags_none" ON (
6+
"books"."id" = "books_x_tags_none"."book_id"
7+
)
8+
LEFT JOIN "tags" AS "tags_none" ON (
9+
(
10+
"books_x_tags_none"."tag_id" = "tags_none"."id"
11+
)
12+
AND "tags_none"."id" = 2
13+
)
14+
GROUP BY
15+
"books"."title",
16+
"books"."id"
17+
HAVING
18+
("books"."title" = 'Book 1')
19+
OR (
20+
COUNT("tags_none"."id") = 0
21+
);
22+
23+
SELECT
24+
"books".*
25+
FROM
26+
"books" AS "books"
27+
LEFT JOIN "books_x_tags" AS "books_x_tags_none" ON (
28+
"books"."id" = "books_x_tags_none"."book_id"
29+
)
30+
LEFT JOIN "tags" AS "tags_none" ON (
31+
(
32+
"books_x_tags_none"."tag_id" = "tags_none"."id"
33+
)
34+
AND "tags_none"."id" = 2
35+
)
36+
WHERE
37+
"books"."title" = 'Book 1'
38+
GROUP BY
39+
"books"."id"
40+
HAVING
41+
COUNT("tags_none"."id") = 0;
42+
43+
SELECT
44+
"books".*
45+
FROM
46+
"books" AS "books"
47+
LEFT JOIN "books_x_tags" AS "books_x_tags_none" ON (
48+
"books"."id" = "books_x_tags_none"."book_id"
49+
)
50+
LEFT JOIN "tags" AS "tags_none" ON (
51+
(
52+
"books_x_tags_none"."tag_id" = "tags_none"."id"
53+
)
54+
AND "tags_none"."id" = 3
55+
)
56+
WHERE
57+
"books"."title" = 'Book 1'
58+
GROUP BY
59+
"books"."id"
60+
HAVING
61+
COUNT("tags_none"."id") = 0;

0 commit comments

Comments
 (0)