|
4 | 4 |
|
5 | 5 | namespace Doctrine\DBAL\Tests\Functional\Query;
|
6 | 6 |
|
| 7 | +use Doctrine\DBAL\ArrayParameterType; |
7 | 8 | use Doctrine\DBAL\DriverManager;
|
8 | 9 | use Doctrine\DBAL\Exception;
|
9 | 10 | use Doctrine\DBAL\ParameterType;
|
10 | 11 | use Doctrine\DBAL\Platforms\DB2Platform;
|
| 12 | +use Doctrine\DBAL\Platforms\Exception\NotSupported; |
11 | 13 | use Doctrine\DBAL\Platforms\MariaDB1060Platform;
|
12 | 14 | use Doctrine\DBAL\Platforms\MariaDBPlatform;
|
13 | 15 | use Doctrine\DBAL\Platforms\MySQL80Platform;
|
@@ -332,6 +334,117 @@ public function testUnionAndAddUnionWorksWithQueryBuilderPartsAndReturnsExpected
|
332 | 334 | self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative());
|
333 | 335 | }
|
334 | 336 |
|
| 337 | + public function testSelectWithCTENamedParameter(): void |
| 338 | + { |
| 339 | + if (! $this->platformSupportsCTEs()) { |
| 340 | + self::markTestSkipped('The database platform does not support CTE.'); |
| 341 | + } |
| 342 | + |
| 343 | + if (! $this->platformSupportsCTEColumnDefinition()) { |
| 344 | + self::markTestSkipped('The database platform does not support CTE column definition.'); |
| 345 | + } |
| 346 | + |
| 347 | + $expectedRows = $this->prepareExpectedRows([['virtual_id' => 1]]); |
| 348 | + $qb = $this->connection->createQueryBuilder(); |
| 349 | + |
| 350 | + $cteQueryBuilder = $this->connection->createQueryBuilder(); |
| 351 | + $cteQueryBuilder->select('id AS virtual_id') |
| 352 | + ->from('for_update') |
| 353 | + ->where('virtual_id = :id'); |
| 354 | + |
| 355 | + $qb->with('cte_a', $cteQueryBuilder, ['virtual_id']) |
| 356 | + ->select('virtual_id') |
| 357 | + ->from('cte_a') |
| 358 | + ->setParameter('id', 1); |
| 359 | + |
| 360 | + self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative()); |
| 361 | + } |
| 362 | + |
| 363 | + public function testSelectWithCTEPositionalParameter(): void |
| 364 | + { |
| 365 | + if (! $this->platformSupportsCTEs()) { |
| 366 | + self::markTestSkipped('The database platform does not support CTE.'); |
| 367 | + } |
| 368 | + |
| 369 | + if (! $this->platformSupportsCTEColumnDefinition()) { |
| 370 | + self::markTestSkipped('The database platform does not support CTE column definition.'); |
| 371 | + } |
| 372 | + |
| 373 | + $expectedRows = $this->prepareExpectedRows([['virtual_id' => 1]]); |
| 374 | + $qb = $this->connection->createQueryBuilder(); |
| 375 | + |
| 376 | + $cteQueryBuilder1 = $this->connection->createQueryBuilder(); |
| 377 | + $cteQueryBuilder1->select('id AS virtual_id') |
| 378 | + ->from('for_update') |
| 379 | + ->where($qb->expr()->eq('virtual_id', '?')); |
| 380 | + |
| 381 | + $cteQueryBuilder2 = $this->connection->createQueryBuilder(); |
| 382 | + $cteQueryBuilder2->select('id AS virtual_id') |
| 383 | + ->from('for_update') |
| 384 | + ->where($qb->expr()->in('id', '?')); |
| 385 | + |
| 386 | + $qb->with('cte_a', $cteQueryBuilder1, ['virtual_id']) |
| 387 | + ->with('cte_b', $cteQueryBuilder2, ['virtual_id']) |
| 388 | + ->select('a.virtual_id') |
| 389 | + ->from('cte_a', 'a') |
| 390 | + ->join('a', 'cte_b', 'b', 'a.virtual_id = b.virtual_id') |
| 391 | + ->setParameters([1, [1, 2]], [ParameterType::INTEGER, ArrayParameterType::INTEGER]); |
| 392 | + |
| 393 | + self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative()); |
| 394 | + } |
| 395 | + |
| 396 | + public function testSelectWithCTEUnion(): void |
| 397 | + { |
| 398 | + if (! $this->platformSupportsCTEs()) { |
| 399 | + self::markTestSkipped('The database platform does not support CTE.'); |
| 400 | + } |
| 401 | + |
| 402 | + $expectedRows = $this->prepareExpectedRows([['id' => 2], ['id' => 1]]); |
| 403 | + $qb = $this->connection->createQueryBuilder(); |
| 404 | + |
| 405 | + $subQueryBuilder1 = $this->connection->createQueryBuilder(); |
| 406 | + $subQueryBuilder1->select('id') |
| 407 | + ->from('for_update') |
| 408 | + ->where($qb->expr()->eq('id', '?')); |
| 409 | + |
| 410 | + $subQueryBuilder2 = $this->connection->createQueryBuilder(); |
| 411 | + $subQueryBuilder2->select('id') |
| 412 | + ->from('for_update') |
| 413 | + ->where($qb->expr()->eq('id', '?')); |
| 414 | + |
| 415 | + $subQueryBuilder3 = $this->connection->createQueryBuilder(); |
| 416 | + $subQueryBuilder3->union($subQueryBuilder1) |
| 417 | + ->addUnion($subQueryBuilder2, UnionType::DISTINCT); |
| 418 | + |
| 419 | + $qb->with('cte_a', $subQueryBuilder3) |
| 420 | + ->select('id') |
| 421 | + ->from('cte_a') |
| 422 | + ->orderBy('id', 'DESC') |
| 423 | + ->setParameters([1, 2]); |
| 424 | + |
| 425 | + self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative()); |
| 426 | + } |
| 427 | + |
| 428 | + public function testPlatformDoesNotSupportCTE(): void |
| 429 | + { |
| 430 | + if ($this->platformSupportsCTEs()) { |
| 431 | + self::markTestSkipped('The database platform does support CTE.'); |
| 432 | + } |
| 433 | + |
| 434 | + $qb = $this->connection->createQueryBuilder(); |
| 435 | + |
| 436 | + $cteQueryBuilder = $this->connection->createQueryBuilder(); |
| 437 | + $cteQueryBuilder->select('id') |
| 438 | + ->from('for_update'); |
| 439 | + |
| 440 | + $qb->with('cte_a', $cteQueryBuilder) |
| 441 | + ->select('id') |
| 442 | + ->from('cte_a'); |
| 443 | + |
| 444 | + self::expectException(NotSupported::class); |
| 445 | + $qb->executeQuery(); |
| 446 | + } |
| 447 | + |
335 | 448 | /**
|
336 | 449 | * @param array<array<string, int>> $rows
|
337 | 450 | *
|
@@ -380,4 +493,16 @@ private function platformSupportsSkipLocked(): bool
|
380 | 493 |
|
381 | 494 | return ! $platform instanceof SQLitePlatform;
|
382 | 495 | }
|
| 496 | + |
| 497 | + private function platformSupportsCTEs(): bool |
| 498 | + { |
| 499 | + $platform = $this->connection->getDatabasePlatform(); |
| 500 | + |
| 501 | + return ! $platform instanceof MySQLPlatform || $platform instanceof MySQL80Platform; |
| 502 | + } |
| 503 | + |
| 504 | + private function platformSupportsCTEColumnDefinition(): bool |
| 505 | + { |
| 506 | + return $this->connection->getDatabasePlatform() instanceof SQLitePlatform; |
| 507 | + } |
383 | 508 | }
|
0 commit comments