Skip to content

Commit ada5563

Browse files
feat: extend support of REGEXP_LIKE() and REGEXP_MATCH() while deprecating the legacy limited flagged variations of FlaggedRegexpLike, FlaggedRegexpMatch and FlaggedRegexpReplace
1 parent 9959476 commit ada5563

File tree

11 files changed

+124
-24
lines changed

11 files changed

+124
-24
lines changed

docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,9 @@
8282
| least | LEAST | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least` |
8383
| numrange | NUMRANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange` |
8484
| overlaps | DATE_OVERLAPS | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateOverlaps` |
85-
| regexp_like (with flags) | FLAGGED_REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpLike` |
86-
| regexp_like (with no flags) | REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike` |
87-
| regexp_match (with flags) | FLAGGED_REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpMatch` |
88-
| regexp_match (with no flags) | REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch` |
89-
| regexp_replace (with flags) | FLAGGED_REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpReplace` |
90-
| regexp_replace (with no flags) | REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace` |
85+
| regexp_like | REGEXP_LIKE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike` |
86+
| regexp_match | REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch` |
87+
| regexp_replace | REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace` |
9188
| row | ROW | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row` |
9289
| row_to_json | ROW_TO_JSON | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson` |
9390
| split_part | SPLIT_PART | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart` |

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpLike.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
66

77
/**
8-
* Implementation of PostgreSQL REGEXP_LIKE() with flags.
8+
* @deprecated This function will be dropped in v4.0. Use RegexpLike instead.
99
*
10+
* Implementation of PostgreSQL REGEXP_LIKE() with flags.
1011
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
1112
* @see https://www.postgresql.org/docs/15/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE
1213
* @since 2.0

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpMatch.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
66

77
/**
8-
* Implementation of PostgreSQL REGEXP_MATCH() with flags.
8+
* @deprecated This function will be dropped in v4.0. Use RegexpMatch instead.
99
*
10+
* Implementation of PostgreSQL REGEXP_MATCH() with flags.
1011
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
1112
* @see https://www.postgresql.org/docs/15/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE
1213
* @since 2.0

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpReplace.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
66

77
/**
8-
* Implementation of PostgreSQL REGEXP_REPLACE().
8+
* @deprecated This function will be dropped in v4.0. Use RegexpReplace instead.
99
*
10+
* Implementation of PostgreSQL REGEXP_REPLACE().
1011
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
1112
* @since 2.5
1213
*

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpLike.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,39 @@
77
/**
88
* Implementation of PostgreSQL REGEXP_LIKE().
99
*
10-
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
10+
* Returns true if a string matches a POSIX regular expression pattern, or false if it does not.
11+
*
12+
* @see https://www.postgresql.org/docs/17/functions-matching.html#FUNCTIONS-POSIX-REGEXP
1113
* @since 2.0
1214
*
1315
* @author Martin Georgiev <martin.georgiev@gmail.com>
16+
*
17+
* @example Using it in DQL: "SELECT REGEXP_LIKE(e.text, 'pattern', 3, 'i') FROM Entity e"
1418
*/
15-
class RegexpLike extends BaseRegexpFunction
19+
class RegexpLike extends BaseVariadicFunction
1620
{
21+
protected function getNodeMappingPattern(): array
22+
{
23+
return [
24+
'StringPrimary,StringPrimary,ArithmeticPrimary,StringPrimary',
25+
'StringPrimary,StringPrimary,ArithmeticPrimary',
26+
'StringPrimary,StringPrimary,StringPrimary',
27+
'StringPrimary,StringPrimary',
28+
];
29+
}
30+
1731
protected function getFunctionName(): string
1832
{
1933
return 'regexp_like';
2034
}
2135

22-
protected function getParameterCount(): int
36+
protected function getMinArgumentCount(): int
2337
{
2438
return 2;
2539
}
40+
41+
protected function getMaxArgumentCount(): int
42+
{
43+
return 4;
44+
}
2645
}

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatch.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,39 @@
77
/**
88
* Implementation of PostgreSQL REGEXP_MATCH().
99
*
10-
* @see https://www.postgresql.org/docs/15/functions-matching.html#FUNCTIONS-POSIX-REGEXP
10+
* Returns the first substring(s) that match a POSIX regular expression pattern, or NULL if there is no match.
11+
*
12+
* @see https://www.postgresql.org/docs/17/functions-matching.html#FUNCTIONS-POSIX-REGEXP
1113
* @since 2.0
1214
*
1315
* @author Martin Georgiev <martin.georgiev@gmail.com>
16+
*
17+
* @example Using it in DQL: "SELECT REGEXP_MATCH(e.text, 'pattern', 3, 'i') FROM Entity e"
1418
*/
15-
class RegexpMatch extends BaseRegexpFunction
19+
class RegexpMatch extends BaseVariadicFunction
1620
{
21+
protected function getNodeMappingPattern(): array
22+
{
23+
return [
24+
'StringPrimary,StringPrimary,ArithmeticPrimary,StringPrimary',
25+
'StringPrimary,StringPrimary,ArithmeticPrimary',
26+
'StringPrimary,StringPrimary,StringPrimary',
27+
'StringPrimary,StringPrimary',
28+
];
29+
}
30+
1731
protected function getFunctionName(): string
1832
{
1933
return 'regexp_match';
2034
}
2135

22-
protected function getParameterCount(): int
36+
protected function getMinArgumentCount(): int
2337
{
2438
return 2;
2539
}
40+
41+
protected function getMaxArgumentCount(): int
42+
{
43+
return 4;
44+
}
2645
}

tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpLikeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class FlaggedRegexpLikeTest extends TestCase
1212
protected function getStringFunctions(): array
1313
{
1414
return [
15-
'FLAGGED_REGEXP_LIKE' => FlaggedRegexpLike::class,
15+
'FLAGGED_REGEXP_LIKE' => FlaggedRegexpLike::class, // @phpstan-ignore-line
1616
];
1717
}
1818

tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpMatchTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class FlaggedRegexpMatchTest extends TestCase
1212
protected function getStringFunctions(): array
1313
{
1414
return [
15-
'FLAGGED_REGEXP_MATCH' => FlaggedRegexpMatch::class,
15+
'FLAGGED_REGEXP_MATCH' => FlaggedRegexpMatch::class, // @phpstan-ignore-line
1616
];
1717
}
1818

tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/FlaggedRegexpReplaceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class FlaggedRegexpReplaceTest extends TestCase
1212
protected function getStringFunctions(): array
1313
{
1414
return [
15-
'FLAGGED_REGEXP_REPLACE' => FlaggedRegexpReplace::class,
15+
'FLAGGED_REGEXP_REPLACE' => FlaggedRegexpReplace::class, // @phpstan-ignore-line
1616
];
1717
}
1818

tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpLikeTest.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@
55
namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
66

77
use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts;
8+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction;
9+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
810
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike;
911

10-
class RegexpLikeTest extends TestCase
12+
class RegexpLikeTest extends BaseVariadicFunctionTestCase
1113
{
14+
protected function createFixture(): BaseVariadicFunction
15+
{
16+
return new RegexpLike('REGEXP_LIKE');
17+
}
18+
1219
protected function getStringFunctions(): array
1320
{
1421
return [
@@ -19,14 +26,38 @@ protected function getStringFunctions(): array
1926
protected function getExpectedSqlStatements(): array
2027
{
2128
return [
22-
"SELECT regexp_like(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
29+
'basic match' => "SELECT regexp_like(c0_.text1, 'pattern') AS sclr_0 FROM ContainsTexts c0_",
30+
'with flags' => "SELECT regexp_like(c0_.text1, 'pattern', 'i') AS sclr_0 FROM ContainsTexts c0_",
31+
'with start position' => "SELECT regexp_like(c0_.text1, 'pattern', 3) AS sclr_0 FROM ContainsTexts c0_",
32+
'with start position and flags' => "SELECT regexp_like(c0_.text1, 'pattern', 3, 'i') AS sclr_0 FROM ContainsTexts c0_",
2333
];
2434
}
2535

2636
protected function getDqlStatements(): array
2737
{
2838
return [
29-
\sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
39+
'basic match' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern') FROM %s e", ContainsTexts::class),
40+
'with flags' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 'i') FROM %s e", ContainsTexts::class),
41+
'with start position' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3) FROM %s e", ContainsTexts::class),
42+
'with start position and flags' => \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3, 'i') FROM %s e", ContainsTexts::class),
3043
];
3144
}
45+
46+
public function test_too_few_arguments_throws_exception(): void
47+
{
48+
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
49+
$this->expectExceptionMessage('regexp_like() requires at least 2 arguments');
50+
51+
$dql = \sprintf('SELECT REGEXP_LIKE(e.text1) FROM %s e', ContainsTexts::class);
52+
$this->buildEntityManager()->createQuery($dql)->getSQL();
53+
}
54+
55+
public function test_too_many_arguments_throws_exception(): void
56+
{
57+
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
58+
$this->expectExceptionMessage('regexp_like() requires between 2 and 4 arguments');
59+
60+
$dql = \sprintf("SELECT REGEXP_LIKE(e.text1, 'pattern', 3, 'i', 'extra_arg') FROM %s e", ContainsTexts::class);
61+
$this->buildEntityManager()->createQuery($dql)->getSQL();
62+
}
3263
}

0 commit comments

Comments
 (0)