Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 3 additions & 6 deletions docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,9 @@
| least | LEAST | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least` |
| numrange | NUMRANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange` |
| overlaps | DATE_OVERLAPS | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateOverlaps` |
| regexp_like (with flags) | FLAGGED_REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpLike` |
| regexp_like (with no flags) | REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike` |
| regexp_match (with flags) | FLAGGED_REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpMatch` |
| regexp_match (with no flags) | REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch` |
| regexp_replace (with flags) | FLAGGED_REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpReplace` |
| regexp_replace (with no flags) | REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace` |
| regexp_like | REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike` |
| regexp_match | REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch` |
| regexp_replace | REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace` |
| row | ROW | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row` |
| row_to_json | ROW_TO_JSON | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson` |
| split_part | SPLIT_PART | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostgreSQL REGEXP_LIKE() with flags.
* @deprecated This function will be dropped in v4.0. Use RegexpLike instead.
*
* Implementation of PostgreSQL REGEXP_LIKE() with flags.
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* @see https://www.postgresql.org/docs/15/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE
* @since 2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostgreSQL REGEXP_MATCH() with flags.
* @deprecated This function will be dropped in v4.0. Use RegexpMatch instead.
*
* Implementation of PostgreSQL REGEXP_MATCH() with flags.
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* @see https://www.postgresql.org/docs/15/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE
* @since 2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

/**
* Implementation of PostgreSQL REGEXP_REPLACE().
* @deprecated This function will be dropped in v4.0. Use RegexpReplace instead.
*
* Implementation of PostgreSQL REGEXP_REPLACE().
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* @since 2.5
*
Expand Down
25 changes: 22 additions & 3 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpLike.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,39 @@
/**
* Implementation of PostgreSQL REGEXP_LIKE().
*
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* Returns true if a string matches a POSIX regular expression pattern, or false if it does not.
*
* @see https://www.postgresql.org/docs/17/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* @since 2.0
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT REGEXP_LIKE(e.text, 'pattern', 3, 'i') FROM Entity e"
*/
class RegexpLike extends BaseRegexpFunction
class RegexpLike extends BaseVariadicFunction
{
protected function getNodeMappingPattern(): array
{
return [
'StringPrimary,StringPrimary,ArithmeticPrimary,StringPrimary',
'StringPrimary,StringPrimary,ArithmeticPrimary',
'StringPrimary,StringPrimary,StringPrimary',
'StringPrimary,StringPrimary',
];
}

protected function getFunctionName(): string
{
return 'regexp_like';
}

protected function getParameterCount(): int
protected function getMinArgumentCount(): int
{
return 2;
}

protected function getMaxArgumentCount(): int
{
return 4;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,39 @@
/**
* Implementation of PostgreSQL REGEXP_MATCH().
*
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* Returns the first substring(s) that match a POSIX regular expression pattern, or NULL if there is no match.
*
* @see https://www.postgresql.org/docs/17/functions-matching.html#FUNCTIONS-POSIX-REGEXP
* @since 2.0
*
* @author Martin Georgiev <martin.georgiev@gmail.com>
*
* @example Using it in DQL: "SELECT REGEXP_MATCH(e.text, 'pattern', 3, 'i') FROM Entity e"
*/
class RegexpMatch extends BaseRegexpFunction
class RegexpMatch extends BaseVariadicFunction
{
protected function getNodeMappingPattern(): array
{
return [
'StringPrimary,StringPrimary,ArithmeticPrimary,StringPrimary',
'StringPrimary,StringPrimary,ArithmeticPrimary',
'StringPrimary,StringPrimary,StringPrimary',
'StringPrimary,StringPrimary',
];
}

protected function getFunctionName(): string
{
return 'regexp_match';
}

protected function getParameterCount(): int
protected function getMinArgumentCount(): int
{
return 2;
}

protected function getMaxArgumentCount(): int
{
return 4;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FlaggedRegexpLikeTest extends TestCase
protected function getStringFunctions(): array
{
return [
'FLAGGED_REGEXP_LIKE' => FlaggedRegexpLike::class,
'FLAGGED_REGEXP_LIKE' => FlaggedRegexpLike::class, // @phpstan-ignore-line
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FlaggedRegexpMatchTest extends TestCase
protected function getStringFunctions(): array
{
return [
'FLAGGED_REGEXP_MATCH' => FlaggedRegexpMatch::class,
'FLAGGED_REGEXP_MATCH' => FlaggedRegexpMatch::class, // @phpstan-ignore-line
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FlaggedRegexpReplaceTest extends TestCase
protected function getStringFunctions(): array
{
return [
'FLAGGED_REGEXP_REPLACE' => FlaggedRegexpReplace::class,
'FLAGGED_REGEXP_REPLACE' => FlaggedRegexpReplace::class, // @phpstan-ignore-line
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

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

class RegexpLikeTest extends TestCase
class RegexpLikeTest extends BaseVariadicFunctionTestCase
{
protected function createFixture(): BaseVariadicFunction
{
return new RegexpLike('REGEXP_LIKE');
}

protected function getStringFunctions(): array
{
return [
Expand All @@ -19,14 +26,38 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
"SELECT regexp_like(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
'basic match' => "SELECT regexp_like(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
'with flags' => "SELECT regexp_like(c0_.text1, 'pattern', 'i') AS sclr_0 FROM ContainsTexts c0_",
'with start position' => "SELECT regexp_like(c0_.text1, 'pattern', 3) AS sclr_0 FROM ContainsTexts c0_",
'with start position and flags' => "SELECT regexp_like(c0_.text1, 'pattern', 3, 'i') AS sclr_0 FROM ContainsTexts c0_",
];
}

protected function getDqlStatements(): array
{
return [
\sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
'basic match' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
'with flags' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 'i') FROM %s e", ContainsTexts::class),
'with start position' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3) FROM %s e", ContainsTexts::class),
'with start position and flags' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3, 'i') FROM %s e", ContainsTexts::class),
];
}

public function test_too_few_arguments_throws_exception(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('regexp_like() requires at least 2 arguments');

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

public function test_too_many_arguments_throws_exception(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('regexp_like() requires between 2 and 4 arguments');

$dql = \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3, 'i', 'extra_arg') FROM %s e", ContainsTexts::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

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

class RegexpMatchTest extends TestCase
class RegexpMatchTest extends BaseVariadicFunctionTestCase
{
protected function createFixture(): BaseVariadicFunction
{
return new RegexpMatch('REGEXP_MATCH');
}

protected function getStringFunctions(): array
{
return [
Expand All @@ -19,14 +26,38 @@ protected function getStringFunctions(): array
protected function getExpectedSqlStatements(): array
{
return [
"SELECT regexp_match(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
'basic match' => "SELECT regexp_match(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
'with flags' => "SELECT regexp_match(c0_.text1, 'pattern', 'i') AS sclr_0 FROM ContainsTexts c0_",
'with start position' => "SELECT regexp_match(c0_.text1, 'pattern', 3) AS sclr_0 FROM ContainsTexts c0_",
'with start position and flags' => "SELECT regexp_match(c0_.text1, 'pattern', 3, 'i') AS sclr_0 FROM ContainsTexts c0_",
];
}

protected function getDqlStatements(): array
{
return [
\sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
'basic match' => \sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
'with flags' => \sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern', 'i') FROM %s e", ContainsTexts::class),
'with start position' => \sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern', 3) FROM %s e", ContainsTexts::class),
'with start position and flags' => \sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern', 3, 'i') FROM %s e", ContainsTexts::class),
];
}

public function test_too_few_arguments_throws_exception(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('regexp_match() requires at least 2 arguments');

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

public function test_too_many_arguments_throws_exception(): void
{
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
$this->expectExceptionMessage('regexp_match() requires between 2 and 4 arguments');

$dql = \sprintf("SELECT REGEXP_MATCH(e.text1, 'pattern', 3, 'i', 'extra_arg') FROM %s e", ContainsTexts::class);
$this->buildEntityManager()->createQuery($dql)->getSQL();
}
}
Loading