-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
248 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
CHANGELOG | ||
========= | ||
|
||
1.2 | ||
--- | ||
|
||
* TABLESAMPLE walker (SYSTEM/BERNOULLI) | ||
|
||
1.1 | ||
--- | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* Copyright (c) 2023 Maksim Tugaev | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
* | ||
* @see https://github.com/tugmaks/doctrine-walkers | ||
*/ | ||
|
||
namespace Tugmaks\DoctrineWalkers\Tablesample; | ||
|
||
final class Tablesample | ||
{ | ||
public function __construct(private readonly TablesampleMethod $tablesampleMethod, private readonly float $percentage) | ||
{ | ||
if (0.00 > $percentage || 100.00 < $percentage) { | ||
throw new TablesampleWalkerException('A percentage must be between 0 and 100'); | ||
} | ||
} | ||
|
||
public function toSQL(): string | ||
{ | ||
return 'TABLESAMPLE ' . | ||
$this->tablesampleMethod->name . | ||
'(' . | ||
$this->percentage . | ||
')'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* Copyright (c) 2023 Maksim Tugaev | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
* | ||
* @see https://github.com/tugmaks/doctrine-walkers | ||
*/ | ||
|
||
namespace Tugmaks\DoctrineWalkers\Tablesample; | ||
|
||
enum TablesampleMethod | ||
{ | ||
case BERNOULLI; | ||
case SYSTEM; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* Copyright (c) 2023 Maksim Tugaev | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
* | ||
* @see https://github.com/tugmaks/doctrine-walkers | ||
*/ | ||
|
||
namespace Tugmaks\DoctrineWalkers\Tablesample; | ||
|
||
use Doctrine\ORM\Query; | ||
use Doctrine\ORM\Query\SqlWalker; | ||
|
||
final class TablesampleWalker extends SqlWalker | ||
{ | ||
public const TABLESAMPLE_RULE = 'TablesampleWalker.Rule'; | ||
|
||
/** | ||
* @param \Doctrine\ORM\Query\AST\FromClause $fromClause | ||
* | ||
* @throws Query\QueryException | ||
*/ | ||
public function walkFromClause($fromClause): string | ||
{ | ||
/** @var array<\Doctrine\ORM\Query\AST\IdentificationVariableDeclaration> $identificationVarDecls */ | ||
$identificationVarDecls = $fromClause->identificationVariableDeclarations; | ||
$sqlParts = []; | ||
|
||
/** @var array<class-string, Tablesample> $hint */ | ||
$hint = $this->getQuery()->getHint(self::TABLESAMPLE_RULE); | ||
|
||
foreach ($identificationVarDecls as $identificationVariableDecl) { | ||
$sqlPart = $this->walkIdentificationVariableDeclaration($identificationVariableDecl); | ||
$candidate = $hint[$identificationVariableDecl->rangeVariableDeclaration?->abstractSchemaName] ?? null; | ||
|
||
if ($candidate instanceof Tablesample) { | ||
$sqlPart .= ' ' . $candidate->toSQL(); | ||
} | ||
|
||
$sqlParts[] = $sqlPart; | ||
} | ||
|
||
return ' FROM ' . \implode(', ', $sqlParts); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* Copyright (c) 2023 Maksim Tugaev | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
* | ||
* @see https://github.com/tugmaks/doctrine-walkers | ||
*/ | ||
|
||
namespace Tugmaks\DoctrineWalkers\Tablesample; | ||
|
||
use LogicException; | ||
|
||
final class TablesampleWalkerException extends LogicException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* Copyright (c) 2023 Maksim Tugaev | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
* | ||
* @see https://github.com/tugmaks/doctrine-walkers | ||
*/ | ||
|
||
namespace Tugmaks\DoctrineWalkersTest\Tablesample; | ||
|
||
use Doctrine\ORM\Query; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use Tugmaks\DoctrineWalkers\Ordering\NULLS; | ||
use Tugmaks\DoctrineWalkers\Tablesample\Tablesample; | ||
use Tugmaks\DoctrineWalkers\Tablesample\TablesampleMethod; | ||
use Tugmaks\DoctrineWalkers\Tablesample\TablesampleWalker; | ||
use Tugmaks\DoctrineWalkers\Tablesample\TablesampleWalkerException; | ||
use Tugmaks\DoctrineWalkersTest\AbstractWalkerTestCase; | ||
use Tugmaks\DoctrineWalkersTest\DummyEntity; | ||
|
||
final class TablesampleWalkerTest extends AbstractWalkerTestCase | ||
{ | ||
/** | ||
* @covers \Tugmaks\DoctrineWalkers\Tablesample\TablesampleWalker | ||
* | ||
* @dataProvider tablesamples | ||
* | ||
* @param array<string, NULLS> $hint | ||
*/ | ||
public function testTablesampleWalker(string $dql, array $hint, string $sql): void | ||
{ | ||
$query = $this->entityManager->createQuery($dql); | ||
|
||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, TablesampleWalker::class); | ||
$query->setHint(TablesampleWalker::TABLESAMPLE_RULE, $hint); | ||
|
||
self::assertSame($sql, $query->getSQL()); | ||
} | ||
|
||
/** | ||
* @return iterable<string, array{0:string, 1: array<class-string, Tablesample>, 2:string}> | ||
*/ | ||
public static function tablesamples(): iterable | ||
{ | ||
yield 'BERNOULLI(0.1)' => [ | ||
\sprintf('SELECT d FROM %s d ORDER BY d.name DESC', DummyEntity::class), | ||
[DummyEntity::class => new Tablesample(TablesampleMethod::BERNOULLI, 0.1)], | ||
'SELECT d0_.id AS id_0, d0_.name AS name_1 FROM de_tbl d0_ TABLESAMPLE BERNOULLI(0.1) ORDER BY d0_.name DESC', | ||
]; | ||
|
||
yield 'SYSTEM(0.2)' => [ | ||
\sprintf('SELECT d FROM %s d ORDER BY d.name DESC', DummyEntity::class), | ||
[DummyEntity::class => new Tablesample(TablesampleMethod::SYSTEM, 0.2)], | ||
'SELECT d0_.id AS id_0, d0_.name AS name_1 FROM de_tbl d0_ TABLESAMPLE SYSTEM(0.2) ORDER BY d0_.name DESC', | ||
]; | ||
} | ||
|
||
/** | ||
* @covers \Tugmaks\DoctrineWalkers\Tablesample\TablesampleWalker | ||
* | ||
* @dataProvider invalidPercentage | ||
*/ | ||
public function testItThrowExceptionOnInvalidPercentage(float $percentage): void | ||
{ | ||
self::expectException(TablesampleWalkerException::class); | ||
self::expectExceptionMessage('A percentage must be between 0 and 100'); | ||
|
||
$dql = \sprintf('SELECT d FROM %s d ORDER BY d.name DESC', DummyEntity::class); | ||
|
||
$query = $this->entityManager->createQuery($dql); | ||
|
||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Tablesample::class); | ||
$query->setHint(TablesampleWalker::TABLESAMPLE_RULE, [DummyEntity::class => new Tablesample(TablesampleMethod::SYSTEM, $percentage)]); | ||
|
||
$query->getSQL(); | ||
} | ||
|
||
/** | ||
* @return iterable<int, array<float>> | ||
*/ | ||
public static function invalidPercentage(): iterable | ||
{ | ||
yield [-1.00]; | ||
|
||
yield [101.00]; | ||
} | ||
} |