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 @@ -81,6 +81,10 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string
// When nodeIndex=2, we're about to add the 3rd argument (total: 3)
$foundMoreNodesThanMappingExpected = ($nodeIndex + 1) > $this->getMaxArgumentCount();
if ($foundMoreNodesThanMappingExpected) {
if ($this->getMinArgumentCount() === $this->getMaxArgumentCount()) {
throw InvalidArgumentForVariadicFunctionException::exactCount($this->getFunctionName(), $this->getMinArgumentCount());
}

throw InvalidArgumentForVariadicFunctionException::between($this->getFunctionName(), $this->getMinArgumentCount(), $this->getMaxArgumentCount());
}

Expand Down Expand Up @@ -114,6 +118,10 @@ protected function validateArguments(Node ...$arguments): void
$maxArgumentCount = $this->getMaxArgumentCount();
$argumentCount = \count($arguments);

if ($minArgumentCount === $maxArgumentCount && $argumentCount !== $minArgumentCount) {
throw InvalidArgumentForVariadicFunctionException::exactCount($this->getFunctionName(), $this->getMinArgumentCount());
}

if ($argumentCount < $minArgumentCount) {
throw InvalidArgumentForVariadicFunctionException::atLeast($this->getFunctionName(), $this->getMinArgumentCount());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
'SELECT c0_.id AS id_0 FROM ContainsArrays c0_ WHERE c0_.id > ALL(c0_.textArray)',
'all elements match condition' => 'SELECT c0_.id AS id_0 FROM ContainsArrays c0_ WHERE c0_.id > ALL(c0_.textArray)',
];
}

protected function getDqlStatements(): array
{
return [
\sprintf('SELECT e.id FROM %s e WHERE e.id > ALL_OF(e.textArray)', ContainsArrays::class),
'all elements match condition' => \sprintf('SELECT e.id FROM %s e WHERE e.id > ALL_OF(e.textArray)', ContainsArrays::class),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPosition;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;

class ArrayPositionTest extends BaseVariadicFunctionTestCase
Expand All @@ -31,6 +32,9 @@ protected function getExpectedSqlStatements(): array
'finds numeric element' => 'SELECT array_position(c0_.integerArray, 42) AS sclr_0 FROM ContainsArrays c0_',
'finds element using parameter' => 'SELECT array_position(c0_.textArray, ?) AS sclr_0 FROM ContainsArrays c0_',
'with start position' => "SELECT array_position(c0_.textArray, 'new-value', 2) AS sclr_0 FROM ContainsArrays c0_",
'with zero start position' => "SELECT array_position(c0_.textArray, 'value', 0) AS sclr_0 FROM ContainsArrays c0_",
'with negative start position' => "SELECT array_position(c0_.textArray, 'value', -1) AS sclr_0 FROM ContainsArrays c0_",
'with arithmetic expression as start position' => "SELECT array_position(c0_.textArray, 'value', 1 + 1) AS sclr_0 FROM ContainsArrays c0_",
];
}

Expand All @@ -41,26 +45,36 @@ protected function getDqlStatements(): array
'finds numeric element' => \sprintf('SELECT ARRAY_POSITION(e.integerArray, 42) FROM %s e', ContainsArrays::class),
'finds element using parameter' => \sprintf('SELECT ARRAY_POSITION(e.textArray, :dql_parameter) FROM %s e', ContainsArrays::class),
'with start position' => \sprintf("SELECT ARRAY_POSITION(e.textArray, 'new-value', 2) FROM %s e", ContainsArrays::class),
'with zero start position' => \sprintf("SELECT ARRAY_POSITION(e.textArray, 'value', 0) FROM %s e", ContainsArrays::class),
'with negative start position' => \sprintf("SELECT ARRAY_POSITION(e.textArray, 'value', -1) FROM %s e", ContainsArrays::class),
'with arithmetic expression as start position' => \sprintf("SELECT ARRAY_POSITION(e.textArray, 'value', 1+1) FROM %s e", ContainsArrays::class),
];
}

#[DataProvider('provideInvalidArgumentCountCases')]
#[Test]
public function too_few_arguments_throws_exception(): void
public function throws_exception_for_invalid_argument_count(string $dql, string $expectedMessage): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('array_position() requires at least 2 arguments');
$this->expectExceptionMessage($expectedMessage);

$dql = \sprintf('SELECT ARRAY_POSITION(e.textArray) FROM %s e', ContainsArrays::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}

#[Test]
public function too_many_arguments_throws_exception(): void
/**
* @return array<string, array{string, string}>
*/
public static function provideInvalidArgumentCountCases(): array
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('array_position() requires between 2 and 3 arguments');

$dql = \sprintf("SELECT ARRAY_POSITION(e.textArray, 0, 1, 'extra_arg') FROM %s e", ContainsArrays::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
return [
'too few arguments' => [
\sprintf('SELECT ARRAY_POSITION(e.textArray) FROM %s e', ContainsArrays::class),
'array_position() requires at least 2 arguments',
],
'too many arguments' => [
\sprintf("SELECT ARRAY_POSITION(e.textArray, 0, 1, 'extra_arg') FROM %s e", ContainsArrays::class),
'array_position() requires between 2 and 3 arguments',
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected function getDqlStatements(): array
}

#[Test]
public function invalid_boolean_throws_exception(): void
public function throws_exception_for_invalid_boolean_value(): void
{
$this->expectException(InvalidBooleanException::class);
$this->expectExceptionMessage('Invalid boolean value "invalid" provided for array_to_json. Must be "true" or "false".');
Expand All @@ -52,7 +52,7 @@ public function invalid_boolean_throws_exception(): void
}

#[Test]
public function too_many_arguments_throws_exception(): void
public function throws_exception_for_too_many_arguments(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('array_to_json() requires between 1 and 2 arguments');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
'SELECT CEIL(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
'rounds decimal up to nearest integer' => 'SELECT CEIL(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
];
}

protected function getDqlStatements(): array
{
return [
\sprintf('SELECT CEIL(e.decimal1) FROM %s e', ContainsDecimals::class),
'rounds decimal up to nearest integer' => \sprintf('SELECT CEIL(e.decimal1) FROM %s e', ContainsDecimals::class),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateAdd;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidTimezoneException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;

class DateAddTest extends BaseVariadicFunctionTestCase
Expand All @@ -28,50 +29,62 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
'adds 1 day with timezone' => "SELECT date_add(c0_.datetimetz1, '1 day', 'Europe/Sofia') AS sclr_0 FROM ContainsDates c0_",
'adds 2 hours with timezone' => "SELECT date_add(c0_.datetimetz1, '2 hours', 'UTC') AS sclr_0 FROM ContainsDates c0_",
'adds 3 days without timezone' => "SELECT date_add(c0_.datetimetz1, '3 days') AS sclr_0 FROM ContainsDates c0_",
'adds with WHERE clause' => "SELECT c0_.datetimetz1 AS datetimetz1_0 FROM ContainsDates c0_ WHERE date_add(c0_.datetimetz1, '1 day') = '2023-01-02 00:00:00'",
'with timezone (3 arguments)' => "SELECT date_add(c0_.datetimetz1, '1 day', 'Europe/Sofia') AS sclr_0 FROM ContainsDates c0_",
'without timezone (2 arguments)' => "SELECT date_add(c0_.datetimetz1, '3 days') AS sclr_0 FROM ContainsDates c0_",
'used in WHERE clause' => "SELECT c0_.datetimetz1 AS datetimetz1_0 FROM ContainsDates c0_ WHERE date_add(c0_.datetimetz1, '1 day') = '2023-01-02 00:00:00'",
];
}

protected function getDqlStatements(): array
{
return [
'adds 1 day with timezone' => \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Europe/Sofia') FROM %s e", ContainsDates::class),
'adds 2 hours with timezone' => \sprintf("SELECT DATE_ADD(e.datetimetz1, '2 hours', 'UTC') FROM %s e", ContainsDates::class),
'adds 3 days without timezone' => \sprintf("SELECT DATE_ADD(e.datetimetz1, '3 days') FROM %s e", ContainsDates::class),
'adds with WHERE clause' => \sprintf("SELECT e.datetimetz1 FROM %s e WHERE DATE_ADD(e.datetimetz1, '1 day') = '2023-01-02 00:00:00'", ContainsDates::class),
'with timezone (3 arguments)' => \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Europe/Sofia') FROM %s e", ContainsDates::class),
'without timezone (2 arguments)' => \sprintf("SELECT DATE_ADD(e.datetimetz1, '3 days') FROM %s e", ContainsDates::class),
'used in WHERE clause' => \sprintf("SELECT e.datetimetz1 FROM %s e WHERE DATE_ADD(e.datetimetz1, '1 day') = '2023-01-02 00:00:00'", ContainsDates::class),
];
}

#[Test]
public function invalid_timezone_throws_exception(): void
public function throws_exception_for_too_few_arguments(): void
{
$this->expectException(InvalidTimezoneException::class);
$this->expectExceptionMessage('Invalid timezone "Invalid/Timezone" provided for date_add');
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('date_add() requires at least 2 arguments');

$dql = \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Invalid/Timezone') FROM %s e", ContainsDates::class);
$dql = \sprintf('SELECT DATE_ADD(e.datetimetz1) FROM %s e', ContainsDates::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}

#[Test]
public function too_few_arguments_throws_exception(): void
public function throws_exception_for_too_many_arguments(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('date_add() requires at least 2 arguments');
$this->expectExceptionMessage('date_add() requires between 2 and 3 arguments');

$dql = \sprintf('SELECT DATE_ADD(e.datetimetz1) FROM %s e', ContainsDates::class);
$dql = \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Europe/Sofia', 'extra_arg') FROM %s e", ContainsDates::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}

#[DataProvider('provideInvalidTimezoneValues')]
#[Test]
public function too_many_arguments_throws_exception(): void
public function throws_exception_for_invalid_timezone(string $invalidTimezone): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('date_add() requires between 2 and 3 arguments');
$this->expectException(InvalidTimezoneException::class);
$this->expectExceptionMessage(\sprintf('Invalid timezone "%s" provided for date_add. Must be a valid PHP timezone identifier.', $invalidTimezone));

$dql = \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Europe/Sofia', 'extra_arg') FROM %s e", ContainsDates::class);
$dql = \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', '%s') FROM %s e", $invalidTimezone, ContainsDates::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}

/**
* @return array<string, array{string}>
*/
public static function provideInvalidTimezoneValues(): array
{
return [
'empty string' => [''],
'whitespace only' => [' '],
'numeric value' => ['123'],
'invalid timezone' => ['Invalid/Timezone'],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
"SELECT EXTRACT('DAY' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
"SELECT EXTRACT('MONTH' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
"SELECT EXTRACT('YEAR' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE EXTRACT('DAY' FROM c0_.date1) = 7",
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE EXTRACT('MONTH' FROM c0_.date1) = 12",
'extracts day from date' => "SELECT EXTRACT('DAY' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
'extracts month from date' => "SELECT EXTRACT('MONTH' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
'extracts year from date' => "SELECT EXTRACT('YEAR' FROM c0_.date1) AS sclr_0 FROM ContainsDates c0_",
'filters by extracted day' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE EXTRACT('DAY' FROM c0_.date1) = 7",
'filters by extracted month' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE EXTRACT('MONTH' FROM c0_.date1) = 12",
];
}

protected function getDqlStatements(): array
{
return [
\sprintf("SELECT DATE_EXTRACT('DAY', e.date1) FROM %s e", ContainsDates::class),
\sprintf("SELECT DATE_EXTRACT('MONTH', e.date1) FROM %s e", ContainsDates::class),
\sprintf("SELECT DATE_EXTRACT('YEAR', e.date1) FROM %s e", ContainsDates::class),
\sprintf("SELECT e.date1 FROM %s e WHERE DATE_EXTRACT('DAY', e.date1) = 7", ContainsDates::class),
\sprintf("SELECT e.date1 FROM %s e WHERE DATE_EXTRACT('MONTH', e.date1) = 12", ContainsDates::class),
'extracts day from date' => \sprintf("SELECT DATE_EXTRACT('DAY', e.date1) FROM %s e", ContainsDates::class),
'extracts month from date' => \sprintf("SELECT DATE_EXTRACT('MONTH', e.date1) FROM %s e", ContainsDates::class),
'extracts year from date' => \sprintf("SELECT DATE_EXTRACT('YEAR', e.date1) FROM %s e", ContainsDates::class),
'filters by extracted day' => \sprintf("SELECT e.date1 FROM %s e WHERE DATE_EXTRACT('DAY', e.date1) = 7", ContainsDates::class),
'filters by extracted month' => \sprintf("SELECT e.date1 FROM %s e WHERE DATE_EXTRACT('MONTH', e.date1) = 12", ContainsDates::class),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,29 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, c0_.date2) OVERLAPS ('2001-12-21', '2001-12-25') = 0",
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, c0_.date2) OVERLAPS ('2001-12-21', '2001-12-25') = 1",
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, COALESCE(c0_.date2, CURRENT_DATE)) OVERLAPS ('2001-12-21', '2001-12-25') = 1",
"SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, COALESCE(c0_.date2, CURRENT_DATE)) OVERLAPS ('2001-12-21', '2001-12-25') = 0",
'checks non-overlapping date ranges' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, c0_.date2) OVERLAPS ('2001-12-21', '2001-12-25') = 0",
'checks overlapping date ranges' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, c0_.date2) OVERLAPS ('2001-12-21', '2001-12-25') = 1",
'checks overlapping with null handling true' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, COALESCE(c0_.date2, CURRENT_DATE)) OVERLAPS ('2001-12-21', '2001-12-25') = 1",
'checks overlapping with null handling false' => "SELECT c0_.date1 AS date1_0 FROM ContainsDates c0_ WHERE (c0_.date1, COALESCE(c0_.date2, CURRENT_DATE)) OVERLAPS ('2001-12-21', '2001-12-25') = 0",
];
}

protected function getDqlStatements(): array
{
return [
\sprintf(
'checks non-overlapping date ranges' => \sprintf(
"SELECT e.date1 FROM %s e WHERE DATE_OVERLAPS(e.date1, e.date2, '2001-12-21', '2001-12-25') = 0",
ContainsDates::class
),
\sprintf(
'checks overlapping date ranges' => \sprintf(
"SELECT e.date1 FROM %s e WHERE DATE_OVERLAPS(e.date1, e.date2, '2001-12-21', '2001-12-25') = TRUE",
ContainsDates::class
),
\sprintf(
'checks overlapping with null handling true' => \sprintf(
"SELECT e.date1 FROM %s e WHERE DATE_OVERLAPS(e.date1, COALESCE(e.date2, CURRENT_DATE()), '2001-12-21', '2001-12-25') = 1",
ContainsDates::class
),
\sprintf(
'checks overlapping with null handling false' => \sprintf(
"SELECT e.date1 FROM %s e WHERE DATE_OVERLAPS(e.date1, COALESCE(e.date2, CURRENT_DATE()), '2001-12-21', '2001-12-25') = FALSE",
ContainsDates::class
),
Expand Down
Loading
Loading