Skip to content

Commit d688a7f

Browse files
committed
Bind parameters to CTE level
1 parent 6559c32 commit d688a7f

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/Query/QueryBuilder.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,40 @@ public function fetchFirstColumn(): array
309309
*/
310310
public function executeQuery(): Result
311311
{
312+
[$cteParams, $cteParamsTypes] = $this->withQueriesParameters();
313+
312314
return $this->connection->executeQuery(
313315
$this->getSQL(),
314-
$this->params,
315-
$this->types,
316+
array_merge($cteParams, $this->params),
317+
array_merge($cteParamsTypes, $this->types),
316318
$this->resultCacheProfile,
317319
);
318320
}
319321

322+
/**
323+
* Retrieve parameters and types bind on the with queries.
324+
*
325+
* @return array{
326+
* list<mixed>|array<string, mixed>,
327+
* WrapperParameterTypeArray,
328+
* } The parameters and types bind on the with queries.
329+
*/
330+
private function withQueriesParameters(): array
331+
{
332+
$cteParams = $cteParamsTypes = [];
333+
334+
foreach ($this->withParts as $withPart) {
335+
if (! $withPart->query instanceof self) {
336+
continue;
337+
}
338+
339+
$cteParams = array_merge($cteParams, $withPart->query->params);
340+
$cteParamsTypes = array_merge($cteParamsTypes, $withPart->query->types);
341+
}
342+
343+
return [$cteParams, $cteParamsTypes];
344+
}
345+
320346
/**
321347
* Executes an SQL statement and returns the number of affected rows.
322348
*

tests/Functional/Query/QueryBuilderTest.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,17 +350,17 @@ public function testSelectWithCTENamedParameter(): void
350350
$cteQueryBuilder = $this->connection->createQueryBuilder();
351351
$cteQueryBuilder->select('id AS virtual_id')
352352
->from('for_update')
353-
->where('virtual_id = :id');
353+
->where('virtual_id = :id')
354+
->setParameter('id', 1);
354355

355356
$qb->with('cte_a', $cteQueryBuilder, ['virtual_id'])
356357
->select('virtual_id')
357-
->from('cte_a')
358-
->setParameter('id', 1);
358+
->from('cte_a');
359359

360360
self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative());
361361
}
362362

363-
public function testSelectWithCTEPositionalParameter(): void
363+
public function testSelectWithCTEPositionalParametersBindForEachQuery(): void
364364
{
365365
if (! $this->platformSupportsCTEs()) {
366366
self::markTestSkipped('The database platform does not support CTE.');
@@ -376,19 +376,22 @@ public function testSelectWithCTEPositionalParameter(): void
376376
$cteQueryBuilder1 = $this->connection->createQueryBuilder();
377377
$cteQueryBuilder1->select('id AS virtual_id')
378378
->from('for_update')
379-
->where($qb->expr()->eq('virtual_id', '?'));
379+
->where($cteQueryBuilder1->expr()->eq('id', '?'))
380+
->setParameter(0, 1, ParameterType::INTEGER);
380381

381382
$cteQueryBuilder2 = $this->connection->createQueryBuilder();
382383
$cteQueryBuilder2->select('id AS virtual_id')
383384
->from('for_update')
384-
->where($qb->expr()->in('id', '?'));
385+
->where($cteQueryBuilder2->expr()->in('id', ':id'))
386+
->setParameter('id', [1, 2], ArrayParameterType::INTEGER);
385387

386388
$qb->with('cte_a', $cteQueryBuilder1, ['virtual_id'])
387389
->with('cte_b', $cteQueryBuilder2, ['virtual_id'])
388390
->select('a.virtual_id')
389391
->from('cte_a', 'a')
390392
->join('a', 'cte_b', 'b', 'a.virtual_id = b.virtual_id')
391-
->setParameters([1, [1, 2]], [ParameterType::INTEGER, ArrayParameterType::INTEGER]);
393+
->where($qb->expr()->eq('a.virtual_id', '?'))
394+
->setParameter(0, 1, ParameterType::INTEGER);
392395

393396
self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative());
394397
}

0 commit comments

Comments
 (0)