Skip to content

Commit ae31a06

Browse files
rex.deploy: added re_replace() function (#42)
1 parent 59b85f2 commit ae31a06

File tree

5 files changed

+99
-12
lines changed

5 files changed

+99
-12
lines changed

src/rex.deploy/README.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,10 @@ PostgreSQL functions:
14211421
Extracts field ``name`` from a JSON object as a JSON object.
14221422
``re_matches(text, pat)``
14231423
Checks if ``text`` matches the regular expression ``pat``.
1424+
``re_replace(text, pat, repl, [flags])``
1425+
Replaces the substrings that match the regular expression ``pat`` with
1426+
``repl``. By default, performs *case-insensitive* comparison and replaces
1427+
*all* occurrences of the pattern.
14241428
``ft_matches(text, key)``
14251429
Checks if ``text`` contains ``key`` by performing full-text search on
14261430
``text`` value.

src/rex.deploy/src/htsql_rex_deploy/tr/bind.py

+30-6
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
match)
1818
from ..domain import JSONDomain
1919
from .lookup import select_identity
20-
from .signature import (REMatchesSig, FTMatchesSig, FTQueryMatchesSig,
21-
FTHeadlineSig, FTQueryHeadlineSig, FTRankSig, FTQueryRankSig, JoinSig,
22-
AbsSig, SignSig, CeilSig, FloorSig, DivSig, ModSig, ExpSig, PowSig,
23-
LnSig, Log10Sig, LogSig, PiSig, ACosSig, ASinSig, ATanSig, ATan2Sig,
24-
CosSig, CotSig, SinSig, TanSig, RandomSig, JSONGetSig, JSONGetJSONSig,
25-
MedianSig, WidthBucketSig)
20+
from .signature import (REMatchesSig, REReplaceSig, REReplaceWithFlagsSig,
21+
FTMatchesSig, FTQueryMatchesSig, FTHeadlineSig, FTQueryHeadlineSig,
22+
FTRankSig, FTQueryRankSig, JoinSig, AbsSig, SignSig, CeilSig, FloorSig,
23+
DivSig, ModSig, ExpSig, PowSig, LnSig, Log10Sig, LogSig, PiSig, ACosSig,
24+
ASinSig, ATanSig, ATan2Sig, CosSig, CotSig, SinSig, TanSig, RandomSig,
25+
JSONGetSig, JSONGetJSONSig, MedianSig, WidthBucketSig)
2626

2727

2828
class SelectEntity(SelectRecord):
@@ -72,6 +72,30 @@ class BindREMatches(BindMonoFunction):
7272
codomain = BooleanDomain()
7373

7474

75+
class BindREMatches(BindMonoFunction):
76+
77+
call('re_matches')
78+
signature = REMatchesSig
79+
domains = [TextDomain(), TextDomain()]
80+
codomain = BooleanDomain()
81+
82+
83+
class BindREReplace(BindMonoFunction):
84+
85+
call(('re_replace', 3))
86+
signature = REReplaceSig
87+
domains = [TextDomain(), TextDomain(), TextDomain()]
88+
codomain = TextDomain()
89+
90+
91+
class BindREReplaceWithFlags(BindMonoFunction):
92+
93+
call(('re_replace', 4))
94+
signature = REReplaceWithFlagsSig
95+
domains = [TextDomain(), TextDomain(), TextDomain(), TextDomain()]
96+
codomain = TextDomain()
97+
98+
7599
class BindFTMatches(BindMonoFunction):
76100

77101
call('ft_matches')

src/rex.deploy/src/htsql_rex_deploy/tr/dump.py

+19-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
PGSQLDumpDateIncrement, PGSQLDumpDateDecrement)
1212
from ..domain import JSONDomain
1313
from .signature import (
14-
EscapeIdentitySig, REMatchesSig, FTMatchesSig, FTQueryMatchesSig,
15-
FTHeadlineSig, FTQueryHeadlineSig, FTRankSig, FTQueryRankSig, JoinSig,
16-
AbsSig, SignSig, CeilSig, FloorSig, DivSig, ModSig, ExpSig, PowSig,
17-
LnSig, Log10Sig, LogSig, PiSig, ACosSig, ASinSig, ATanSig, ATan2Sig,
18-
CosSig, CotSig, SinSig, TanSig, RandomSig, ToJSONSig, JSONGetSig,
19-
JSONGetJSONSig, MedianSig, WidthBucketSig)
14+
EscapeIdentitySig, REMatchesSig, REReplaceSig, REReplaceWithFlagsSig,
15+
FTMatchesSig, FTQueryMatchesSig, FTHeadlineSig, FTQueryHeadlineSig,
16+
FTRankSig, FTQueryRankSig, JoinSig, AbsSig, SignSig, CeilSig, FloorSig,
17+
DivSig, ModSig, ExpSig, PowSig, LnSig, Log10Sig, LogSig, PiSig,
18+
ACosSig, ASinSig, ATanSig, ATan2Sig, CosSig, CotSig, SinSig, TanSig,
19+
RandomSig, ToJSONSig, JSONGetSig, JSONGetJSONSig, MedianSig,
20+
WidthBucketSig)
2021

2122

2223
class DeployDumpDateIncrement(PGSQLDumpDateIncrement):
@@ -69,6 +70,18 @@ class DumpREMatches(DumpFunction):
6970
template = "({lop} ~* {rop})"
7071

7172

73+
class DumpREReplace(DumpFunction):
74+
75+
adapt(REReplaceSig)
76+
template = "REGEXP_REPLACE({op}, {pat}, {repl}, 'ig')"
77+
78+
79+
class DumpREReplaceWithFlags(DumpFunction):
80+
81+
adapt(REReplaceWithFlagsSig)
82+
template = "REGEXP_REPLACE({op}, {pat}, {repl}, {flags})"
83+
84+
7285
class DumpFTMatches(DumpFunction):
7386

7487
adapt(FTMatchesSig)

src/rex.deploy/src/htsql_rex_deploy/tr/signature.py

+19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@ class REMatchesSig(BinarySig):
2020
pass
2121

2222

23+
class REReplaceSig(Signature):
24+
25+
slots = [
26+
Slot('op'),
27+
Slot('pat'),
28+
Slot('repl'),
29+
]
30+
31+
32+
class REReplaceWithFlagsSig(Signature):
33+
34+
slots = [
35+
Slot('op'),
36+
Slot('pat'),
37+
Slot('repl'),
38+
Slot('flags')
39+
]
40+
41+
2342
class FTMatchesSig(BinarySig):
2443
pass
2544

src/rex.deploy/test/test_htsql_rex_deploy.rst

+27
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,33 @@ To search for a text field with a regular expression, use function
390390
-+------------------------+-------------------------+-
391391
| true | false |
392392

393+
To search and replace a text value with a regular expression, use function
394+
``re_replace``::
395+
396+
>>> q = Query(''' {re_replace('Alice Ball', '([a-z]+) ([a-z]+)', '\\2, \\1')} ''')
397+
>>> print(q.format('txt').decode('utf-8')) # doctest: +NORMALIZE_WHITESPACE
398+
| re_replace('Alice Ball','([a-z]+) ([a-z]+)','\2, \1') |
399+
-+-------------------------------------------------------+-
400+
| Ball, Alice |
401+
402+
By default, ``re_replace`` performs *case-insensitive* comparison and replaces
403+
*all* occurrences of a pattern::
404+
405+
>>> q = Query(''' {re_replace('[email protected]', '[a-z]', 'X')} ''')
406+
>>> print(q.format('txt').decode('utf-8')) # doctest: +NORMALIZE_WHITESPACE
407+
| re_replace('[email protected]','[a-z]','X') |
408+
-+--------------------------------------------------+-
409+
410+
411+
To change this behavior, specify the desired options as the last parameter to
412+
the function::
413+
414+
>>> q = Query(''' {re_replace('[email protected]', '[a-z]', 'X', 'g')} ''')
415+
>>> print(q.format('txt').decode('utf-8')) # doctest: +NORMALIZE_WHITESPACE
416+
| re_replace('[email protected]','[a-z]','X','g') |
417+
-+------------------------------------------------------+-
418+
419+
393420
``rex.deploy`` also provides interface for full-text search::
394421

395422
>>> q = Query(''' {ft_matches('queries', 'query'), ft_matches('requests', 'query')} ''')

0 commit comments

Comments
 (0)