Skip to content

Commit ef688dc

Browse files
feat: extend support of REGEXP_LIKE(), REGEXP_MATCH() and REGEXP_REPLACE() while deprecating the legacy limited flagged variations of FlaggedRegexpLike, FlaggedRegexpMatch and FlaggedRegexpReplace (#357)
1 parent 7f3aff7 commit ef688dc

14 files changed

+121
-51
lines changed

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

Lines changed: 0 additions & 22 deletions
This file was deleted.

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

Lines changed: 3 additions & 2 deletions
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
@@ -17,7 +18,7 @@ class FlaggedRegexpLike extends BaseFunction
1718
{
1819
protected function customizeFunction(): void
1920
{
20-
$this->setFunctionPrototype('regexp_like(%s, %s, 1, %s)');
21+
$this->setFunctionPrototype('regexp_like(%s, %s, %s)');
2122
$this->addNodeMapping('StringPrimary');
2223
$this->addNodeMapping('StringPrimary');
2324
$this->addNodeMapping('StringPrimary');

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: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,36 @@
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', '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',
25+
];
26+
}
27+
1728
protected function getFunctionName(): string
1829
{
1930
return 'regexp_like';
2031
}
2132

22-
protected function getParameterCount(): int
33+
protected function getMinArgumentCount(): int
2334
{
2435
return 2;
2536
}
37+
38+
protected function getMaxArgumentCount(): int
39+
{
40+
return 3;
41+
}
2642
}

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,36 @@
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', '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',
25+
];
26+
}
27+
1728
protected function getFunctionName(): string
1829
{
1930
return 'regexp_match';
2031
}
2132

22-
protected function getParameterCount(): int
33+
protected function getMinArgumentCount(): int
2334
{
2435
return 2;
2536
}
37+
38+
protected function getMaxArgumentCount(): int
39+
{
40+
return 3;
41+
}
2642
}

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,25 @@
1313
* @since 2.5
1414
*
1515
* @author Colin Doig
16+
* @author Martin Georgiev <martin.georgiev@gmail.com>
1617
*
1718
* @example Using it in DQL: "SELECT REGEXP_REPLACE(e.text, 'pattern', 'replacement', 3, 2, 'i') FROM Entity e"
1819
*/
1920
class RegexpReplace extends BaseVariadicFunction
2021
{
2122
protected function getNodeMappingPattern(): array
2223
{
24+
/*
25+
* PostgreSQL overloads the 4th argument depending on its type:
26+
* - if the 4th arg is a string, it’s taken as flags.
27+
* - if the 4th arg is an integer, it’s taken as start position. This can be extended with the Nth argument.
28+
*/
2329
return [
24-
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary,ArithmeticPrimary,StringPrimary',
25-
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary,ArithmeticPrimary',
26-
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary,StringPrimary',
27-
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary',
28-
'StringPrimary,StringPrimary,StringPrimary,StringPrimary',
29-
'StringPrimary,StringPrimary,StringPrimary',
30+
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary,ArithmeticPrimary,StringPrimary', // with start, N and flags: regexp_replace(string, pattern, replacement, 3, 2, 'i')
31+
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary,ArithmeticPrimary', // with start and N: regexp_replace(string, pattern, replacement, 3, 2)
32+
'StringPrimary,StringPrimary,StringPrimary,ArithmeticPrimary', // with start: regexp_replace(string, pattern, replacement, 3)
33+
'StringPrimary,StringPrimary,StringPrimary,StringPrimary', // with flags: regexp_replace(string, pattern, replacement, 'i')
34+
'StringPrimary,StringPrimary,StringPrimary', // basic replacement: regexp_replace(string, pattern, replacement)
3035
];
3136
}
3237

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function throws_an_exception_when_lexer_is_not_populated_with_a_lookahead
2828
->willReturn(new Configuration());
2929

3030
$query = new Query($em);
31-
$query->setDQL('TRUE');
31+
$query->setDQL('SELECT 1');
3232

3333
$parser = new Parser($query);
3434
$parser->getLexer()->moveNext();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ 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

1919
protected function getExpectedSqlStatements(): array
2020
{
2121
return [
22-
"SELECT regexp_like(c0_.text1, 'pattern', 1, 'i') AS sclr_0 FROM ContainsTexts c0_",
22+
"SELECT regexp_like(c0_.text1, 'pattern', 'i') AS sclr_0 FROM ContainsTexts c0_",
2323
];
2424
}
2525

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

0 commit comments

Comments
 (0)