44
55use Doctrine\ORM\Query;
66use Doctrine\ORM\Query\AST;
7- use function is_string ;
7+ use function is_array ;
88
99class QueryAggregateFunctionDetectorTreeWalker extends Query\TreeWalkerAdapter
1010{
@@ -13,294 +13,38 @@ class QueryAggregateFunctionDetectorTreeWalker extends Query\TreeWalkerAdapter
1313
1414 public function walkSelectStatement(AST\SelectStatement $selectStatement): void
1515 {
16- $this->doWalkSelectClause ($selectStatement->selectClause);
16+ $this->walkNode ($selectStatement->selectClause);
1717 }
1818
1919 /**
20- * @param AST\SelectClause $selectClause
20+ * @param mixed $node
2121 */
22- public function doWalkSelectClause($selectClause ): void
22+ public function walkNode($node ): void
2323 {
24- foreach ($selectClause->selectExpressions as $selectExpression) {
25- $this->doWalkSelectExpression($selectExpression);
26- }
27- }
28-
29- /**
30- * @param AST\SelectExpression $selectExpression
31- */
32- public function doWalkSelectExpression($selectExpression): void
33- {
34- $this->doWalkNode($selectExpression->expression);
35- }
36-
37- /**
38- * @param mixed $expr
39- */
40- private function doWalkNode($expr): void
41- {
42- if ($expr instanceof AST\AggregateExpression) {
43- $this->markAggregateFunctionFound();
44-
45- } elseif ($expr instanceof AST\Functions\FunctionNode) {
46- if ($this->isAggregateFunction($expr)) {
47- $this->markAggregateFunctionFound();
48- }
49-
50- } elseif ($expr instanceof AST\SimpleArithmeticExpression) {
51- foreach ($expr->arithmeticTerms as $term) {
52- $this->doWalkArithmeticTerm($term);
53- }
54-
55- } elseif ($expr instanceof AST\ArithmeticTerm) {
56- $this->doWalkArithmeticTerm($expr);
57-
58- } elseif ($expr instanceof AST\ArithmeticFactor) {
59- $this->doWalkArithmeticFactor($expr);
60-
61- } elseif ($expr instanceof AST\ParenthesisExpression) {
62- $this->doWalkArithmeticPrimary($expr->expression);
63-
64- } elseif ($expr instanceof AST\NullIfExpression) {
65- $this->doWalkNullIfExpression($expr);
66-
67- } elseif ($expr instanceof AST\CoalesceExpression) {
68- $this->doWalkCoalesceExpression($expr);
69-
70- } elseif ($expr instanceof AST\GeneralCaseExpression) {
71- $this->doWalkGeneralCaseExpression($expr);
72-
73- } elseif ($expr instanceof AST\SimpleCaseExpression) {
74- $this->doWalkSimpleCaseExpression($expr);
75-
76- } elseif ($expr instanceof AST\ArithmeticExpression) {
77- $this->doWalkArithmeticExpression($expr);
78-
79- } elseif ($expr instanceof AST\ComparisonExpression) {
80- $this->doWalkComparisonExpression($expr);
81-
82- } elseif ($expr instanceof AST\BetweenExpression) {
83- $this->doWalkBetweenExpression($expr);
84- }
85- }
86-
87- public function doWalkCoalesceExpression(AST\CoalesceExpression $coalesceExpression): void
88- {
89- foreach ($coalesceExpression->scalarExpressions as $scalarExpression) {
90- $this->doWalkSimpleArithmeticExpression($scalarExpression);
91- }
92- }
93-
94- public function doWalkNullIfExpression(AST\NullIfExpression $nullIfExpression): void
95- {
96- if (!is_string($nullIfExpression->firstExpression)) {
97- $this->doWalkSimpleArithmeticExpression($nullIfExpression->firstExpression);
98- }
99-
100- if (is_string($nullIfExpression->secondExpression)) {
24+ if (!$node instanceof AST\Node) {
10125 return;
10226 }
10327
104- $this->doWalkSimpleArithmeticExpression($nullIfExpression->secondExpression);
105- }
106-
107- public function doWalkGeneralCaseExpression(AST\GeneralCaseExpression $generalCaseExpression): void
108- {
109- foreach ($generalCaseExpression->whenClauses as $whenClause) {
110- $this->doWalkConditionalExpression($whenClause->caseConditionExpression);
111- $this->doWalkSimpleArithmeticExpression($whenClause->thenScalarExpression);
112- }
113-
114- $this->doWalkSimpleArithmeticExpression($generalCaseExpression->elseScalarExpression);
115- }
116-
117- public function doWalkSimpleCaseExpression(AST\SimpleCaseExpression $simpleCaseExpression): void
118- {
119- foreach ($simpleCaseExpression->simpleWhenClauses as $simpleWhenClause) {
120- $this->doWalkSimpleArithmeticExpression($simpleWhenClause->caseScalarExpression);
121- $this->doWalkSimpleArithmeticExpression($simpleWhenClause->thenScalarExpression);
122- }
123-
124- $this->doWalkSimpleArithmeticExpression($simpleCaseExpression->elseScalarExpression);
125- }
126-
127- /**
128- * @param AST\ConditionalExpression|AST\Phase2OptimizableConditional $condExpr
129- */
130- public function doWalkConditionalExpression($condExpr): void
131- {
132- if (!$condExpr instanceof AST\ConditionalExpression) {
133- $this->doWalkConditionalTerm($condExpr); // @phpstan-ignore-line PHPStan do not read @psalm-inheritors of Phase2OptimizableConditional
134- return;
135- }
136-
137- foreach ($condExpr->conditionalTerms as $conditionalTerm) {
138- $this->doWalkConditionalTerm($conditionalTerm);
139- }
140- }
141-
142- /**
143- * @param AST\ConditionalTerm|AST\ConditionalPrimary|AST\ConditionalFactor $condTerm
144- */
145- public function doWalkConditionalTerm($condTerm): void
146- {
147- if (!$condTerm instanceof AST\ConditionalTerm) {
148- $this->doWalkConditionalFactor($condTerm);
28+ if ($this->isAggregateFunction($node)) {
29+ $this->markAggregateFunctionFound();
14930 return;
15031 }
15132
152- foreach ($condTerm->conditionalFactors as $conditionalFactor ) {
153- $this->doWalkConditionalFactor($conditionalFactor);
154- }
155- }
33+ foreach ((array) $node as $property ) {
34+ if ($property instanceof AST\Node) {
35+ $this->walkNode($property);
36+ }
15637
157- /**
158- * @param AST\ConditionalFactor|AST\ConditionalPrimary $factor
159- */
160- public function doWalkConditionalFactor($factor): void
161- {
162- if (!$factor instanceof AST\ConditionalFactor) {
163- $this->doWalkConditionalPrimary($factor);
164- } else {
165- $this->doWalkConditionalPrimary($factor->conditionalPrimary);
166- }
167- }
38+ if (is_array($property)) {
39+ foreach ($property as $propertyValue) {
40+ $this->walkNode($propertyValue);
41+ }
42+ }
16843
169- /**
170- * @param AST\ConditionalPrimary $primary
171- */
172- public function doWalkConditionalPrimary($primary): void
173- {
174- if ($primary->isSimpleConditionalExpression()) {
175- if ($primary->simpleConditionalExpression instanceof AST\ComparisonExpression) {
176- $this->doWalkComparisonExpression($primary->simpleConditionalExpression);
44+ if ($this->wasAggregateFunctionFound()) {
17745 return;
17846 }
179- $this->doWalkNode($primary->simpleConditionalExpression);
18047 }
181-
182- if (!$primary->isConditionalExpression()) {
183- return;
184- }
185-
186- if ($primary->conditionalExpression === null) {
187- return;
188- }
189-
190- $this->doWalkConditionalExpression($primary->conditionalExpression);
191- }
192-
193- /**
194- * @param AST\BetweenExpression $betweenExpr
195- */
196- public function doWalkBetweenExpression($betweenExpr): void
197- {
198- $this->doWalkArithmeticExpression($betweenExpr->expression);
199- $this->doWalkArithmeticExpression($betweenExpr->leftBetweenExpression);
200- $this->doWalkArithmeticExpression($betweenExpr->rightBetweenExpression);
201- }
202-
203- /**
204- * @param AST\ComparisonExpression $compExpr
205- */
206- public function doWalkComparisonExpression($compExpr): void
207- {
208- $leftExpr = $compExpr->leftExpression;
209- $rightExpr = $compExpr->rightExpression;
210-
211- if ($leftExpr instanceof AST\Node) {
212- $this->doWalkNode($leftExpr);
213- }
214-
215- if (!($rightExpr instanceof AST\Node)) {
216- return;
217- }
218-
219- $this->doWalkNode($rightExpr);
220- }
221-
222- /**
223- * @param AST\ArithmeticExpression $arithmeticExpr
224- */
225- public function doWalkArithmeticExpression($arithmeticExpr): void
226- {
227- if (!$arithmeticExpr->isSimpleArithmeticExpression()) {
228- return;
229- }
230-
231- if ($arithmeticExpr->simpleArithmeticExpression === null) {
232- return;
233- }
234-
235- $this->doWalkSimpleArithmeticExpression($arithmeticExpr->simpleArithmeticExpression);
236- }
237-
238- /**
239- * @param AST\Node|string $simpleArithmeticExpr
240- */
241- public function doWalkSimpleArithmeticExpression($simpleArithmeticExpr): void
242- {
243- if (!$simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression) {
244- $this->doWalkArithmeticTerm($simpleArithmeticExpr);
245- return;
246- }
247-
248- foreach ($simpleArithmeticExpr->arithmeticTerms as $term) {
249- $this->doWalkArithmeticTerm($term);
250- }
251- }
252-
253- /**
254- * @param AST\Node|string $term
255- */
256- public function doWalkArithmeticTerm($term): void
257- {
258- if (is_string($term)) {
259- return;
260- }
261-
262- if (!$term instanceof AST\ArithmeticTerm) {
263- $this->doWalkArithmeticFactor($term);
264- return;
265- }
266-
267- foreach ($term->arithmeticFactors as $factor) {
268- $this->doWalkArithmeticFactor($factor);
269- }
270- }
271-
272- /**
273- * @param AST\Node|string $factor
274- */
275- public function doWalkArithmeticFactor($factor): void
276- {
277- if (is_string($factor)) {
278- return;
279- }
280-
281- if (!$factor instanceof AST\ArithmeticFactor) {
282- $this->doWalkArithmeticPrimary($factor);
283- return;
284- }
285-
286- $this->doWalkArithmeticPrimary($factor->arithmeticPrimary);
287- }
288-
289- /**
290- * @param AST\Node|string $primary
291- */
292- public function doWalkArithmeticPrimary($primary): void
293- {
294- if ($primary instanceof AST\SimpleArithmeticExpression) {
295- $this->doWalkSimpleArithmeticExpression($primary);
296- return;
297- }
298-
299- if (!($primary instanceof AST\Node)) {
300- return;
301- }
302-
303- $this->doWalkNode($primary);
30448 }
30549
30650 private function isAggregateFunction(AST\Node $node): bool
@@ -318,4 +62,9 @@ private function markAggregateFunctionFound(): void
31862 $this->_getQuery()->setHint(self::HINT_HAS_AGGREGATE_FUNCTION, true);
31963 }
32064
65+ private function wasAggregateFunctionFound(): bool
66+ {
67+ return $this->_getQuery()->hasHint(self::HINT_HAS_AGGREGATE_FUNCTION);
68+ }
69+
32170}
0 commit comments