Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public function feedParserWithNodes(Parser $parser): void
}
$aheadType = $lexer->lookahead->type;
}

$this->validateArguments($this->nodes);
}

public function getSql(SqlWalker $sqlWalker): string
Expand All @@ -49,4 +51,11 @@ public function getSql(SqlWalker $sqlWalker): string

return \sprintf($this->functionPrototype, \implode(', ', $dispatched));
}

/**
* Validates the arguments passed to the function.
*
* @param mixed[] $arguments The array of arguments to validate
*/
abstract protected function validateArguments(array $arguments): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception;

class InvalidArgumentForVariadicFunctionException extends \InvalidArgumentException
{
public static function exactCount(string $functionName, int $expected): self
{
return new self(\sprintf(
'%s() requires exactly %d argument%s',
$functionName,
$expected,
$expected === 1 ? '' : 's'
));
}

public static function atLeast(string $functionName, int $min): self
{
return new self(\sprintf(
'%s() requires at least %d argument%s',
$functionName,
$min,
$min === 1 ? '' : 's'
));
}

public static function between(string $functionName, int $min, int $max): self
{
return new self(\sprintf(
'%s() requires between %d and %d arguments',
$functionName,
$min,
$max
));
}

public static function evenNumber(string $functionName): self
{
return new self(\sprintf(
'%s() requires an even number of arguments',
$functionName
));
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Greatest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL GREATEST().
*
Expand All @@ -18,4 +20,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('greatest(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount < 2) {
throw InvalidArgumentForVariadicFunctionException::atLeast('greatest', 2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,28 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL JSON_BUILD_OBJECT().
*
* @see https://www.postgresql.org/docs/17/functions-json.html
* @since 2.9.0
* @since 2.9
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*/
class JsonBuildObject extends BaseVariadicFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('json_build_object(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount === 0 || $argumentCount % 2 !== 0) {
throw InvalidArgumentForVariadicFunctionException::evenNumber('json_build_object');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,28 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL JSONB_BUILD_OBJECT().
*
* @see https://www.postgresql.org/docs/17/functions-json.html
* @since 2.9.0
* @since 2.9
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*/
class JsonbBuildObject extends BaseVariadicFunction
{
protected function customizeFunction(): void
{
$this->setFunctionPrototype('jsonb_build_object(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount === 0 || $argumentCount % 2 !== 0) {
throw InvalidArgumentForVariadicFunctionException::evenNumber('jsonb_build_object');
}
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Least.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL LEAST().
*
Expand All @@ -18,4 +20,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('least(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount < 2) {
throw InvalidArgumentForVariadicFunctionException::atLeast('least', 2);
}
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Row.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL Row Constructor expression.
*
Expand All @@ -17,4 +19,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('ROW(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount === 0) {
throw InvalidArgumentForVariadicFunctionException::atLeast('ROW', 1);
}
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsquery.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL TO_TSQUERY().
*
Expand All @@ -18,4 +20,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('to_tsquery(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount < 1 || $argumentCount > 2) {
throw InvalidArgumentForVariadicFunctionException::between('to_tsquery', 1, 2);
}
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL TO_TSVECTOR().
*
Expand All @@ -20,4 +22,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('to_tsvector(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount < 1 || $argumentCount > 2) {
throw InvalidArgumentForVariadicFunctionException::between('to_tsvector', 1, 2);
}
}
}
10 changes: 10 additions & 0 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Unaccent.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;

/**
* Implementation of PostgreSQL UNACCENT.
*
Expand All @@ -19,4 +21,12 @@ protected function customizeFunction(): void
{
$this->setFunctionPrototype('unaccent(%s)');
}

protected function validateArguments(array $arguments): void
{
$argumentCount = \count($arguments);
if ($argumentCount < 1 || $argumentCount > 2) {
throw InvalidArgumentForVariadicFunctionException::between('unaccent', 1, 2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseComparisonFunction;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest;

class GreatestTest extends BaseComparisonFunctionTestCase
Expand Down Expand Up @@ -35,4 +36,15 @@ protected function getDqlStatements(): array
\sprintf('SELECT GREATEST(e.integer1, e.integer2, e.integer3) FROM %s e', ContainsIntegers::class),
];
}

/**
* @test
*/
public function throws_exception_when_single_argument_given(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);

$dql = \sprintf('SELECT GREATEST(e.integer1) FROM %s e', ContainsIntegers::class);
$this->assertSqlFromDql('', $dql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonBuildObject;

class JsonBuildObjectTest extends TestCase
Expand Down Expand Up @@ -33,4 +34,15 @@ protected function getDqlStatements(): array
\sprintf("SELECT JSON_BUILD_OBJECT('key1', e.object1, 'key2', e.object2) FROM %s e", ContainsJsons::class),
];
}

/**
* @test
*/
public function throws_exception_when_odd_number_of_arguments_given(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);

$dql = \sprintf('SELECT JSON_BUILD_OBJECT(\'key1\', e.value1, \'key2\') FROM %s e', ContainsJsons::class);
$this->assertSqlFromDql('', $dql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbBuildObject;

class JsonbBuildObjectTest extends TestCase
Expand Down Expand Up @@ -33,4 +34,15 @@ protected function getDqlStatements(): array
\sprintf("SELECT JSONB_BUILD_OBJECT('key1', e.object1, 'key2', e.object2) FROM %s e", ContainsJsons::class),
];
}

/**
* @test
*/
public function throws_exception_when_odd_number_of_arguments_given(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);

$dql = \sprintf('SELECT JSONB_BUILD_OBJECT(\'key1\', e.object1, \'key2\') FROM %s e', ContainsJsons::class);
$this->assertSqlFromDql('', $dql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseComparisonFunction;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least;

class LeastTest extends BaseComparisonFunctionTestCase
Expand Down Expand Up @@ -35,4 +36,15 @@ protected function getDqlStatements(): array
\sprintf('SELECT LEAST(e.integer1, e.integer2, e.integer3) FROM %s e', ContainsIntegers::class),
];
}

/**
* @test
*/
public function throws_exception_when_single_argument_given(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);

$dql = \sprintf('SELECT LEAST(e.integer1) FROM %s e', ContainsIntegers::class);
$this->assertSqlFromDql('', $dql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public function dql_is_transformed_to_valid_sql(): void
}
}

private function assertSqlFromDql(string $expectedSql, string $dql, string $message = ''): void
protected function assertSqlFromDql(string $expectedSql, string $dql, string $message = ''): void
{
$query = $this->buildEntityManager()->createQuery($dql);
$this->assertEquals($expectedSql, $query->getSQL(), $message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery;

class ToTsqueryTest extends TestCase
Expand Down Expand Up @@ -33,4 +34,15 @@ protected function getDqlStatements(): array
\sprintf('SELECT TO_TSQUERY(\'english\', e.text1) FROM %s e', ContainsTexts::class),
];
}

/**
* @test
*/
public function throws_exception_when_too_many_arguments_given(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);

$dql = \sprintf('SELECT TO_TSQUERY(\'english\', e.text1, \'extra\') FROM %s e', ContainsTexts::class);
$this->assertSqlFromDql('', $dql);
}
}
Loading
Loading