PostgreSQL Source Code: src/backend/utils/adt/regexp.c File Reference (original) (raw)
Go to the source code of this file.
Data Structures | |
---|---|
struct | pg_re_flags |
struct | regexp_matches_ctx |
struct | cached_re_str |
Typedefs | |
---|---|
typedef struct pg_re_flags | pg_re_flags |
typedef struct regexp_matches_ctx | regexp_matches_ctx |
typedef struct cached_re_str | cached_re_str |
Variables | |
---|---|
static MemoryContext | RegexpCacheMemoryContext |
static int | num_res = 0 |
static cached_re_str | re_array [MAX_CACHED_RES] |
◆ MAX_CACHED_RES
#define MAX_CACHED_RES 32
◆ PG_GETARG_TEXT_PP_IF_EXISTS
◆ cached_re_str
◆ pg_re_flags
◆ regexp_matches_ctx
◆ build_regexp_match_result()
Definition at line 1620 of file regexp.c.
1621{
1624 bool *nulls = matchctx->nulls;
1625 int dims[1];
1626 int lbs[1];
1627 int loc;
1628 int i;
1629
1630
1633 {
1634 int so = matchctx->match_locs[loc++];
1635 int eo = matchctx->match_locs[loc++];
1636
1637 if (so < 0 || eo < 0)
1638 {
1640 nulls[i] = true;
1641 }
1642 else if (buf)
1643 {
1646 eo - so);
1647
1648 Assert(len < matchctx->conv_bufsiz);
1650 nulls[i] = false;
1651 }
1652 else
1653 {
1658 nulls[i] = false;
1659 }
1660 }
1661
1662
1664 lbs[0] = 1;
1665
1667 TEXTOID, -1, false, TYPALIGN_INT);
1668}
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Assert(PointerIsAligned(start, uint64))
int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
static Datum PointerGetDatum(const void *X)
static Datum Int32GetDatum(int32 X)
Datum text_substr(PG_FUNCTION_ARGS)
text * cstring_to_text_with_len(const char *s, int len)
References Assert(), buf, construct_md_array(), regexp_matches_ctx::conv_buf, cstring_to_text_with_len(), DirectFunctionCall3, regexp_matches_ctx::elems, i, Int32GetDatum(), len, regexp_matches_ctx::match_locs, regexp_matches_ctx::next_match, regexp_matches_ctx::npatterns, regexp_matches_ctx::nulls, regexp_matches_ctx::orig_str, pg_wchar2mb_with_len(), PointerGetDatum(), text_substr(), and regexp_matches_ctx::wide_str.
Referenced by regexp_match(), and regexp_matches().
◆ build_regexp_split_result()
Definition at line 1791 of file regexp.c.
1792{
1796
1799 else
1802 elog(ERROR, "invalid match ending position");
1803
1806 elog(ERROR, "invalid match starting position");
1807
1808 if (buf)
1809 {
1810 int len;
1811
1815 Assert(len < splitctx->conv_bufsiz);
1817 }
1818 else
1819 {
1824 }
1825}
static XLogRecPtr startpos
References Assert(), buf, regexp_matches_ctx::conv_buf, cstring_to_text_with_len(), DirectFunctionCall3, elog, endpos, ERROR, Int32GetDatum(), len, regexp_matches_ctx::match_locs, regexp_matches_ctx::next_match, regexp_matches_ctx::orig_str, pg_wchar2mb_with_len(), PointerGetDatum(), startpos, text_substr(), and regexp_matches_ctx::wide_str.
Referenced by regexp_split_to_array(), and regexp_split_to_table().
◆ nameicregexeq()
Definition at line 522 of file regexp.c.
523{
526
532 0, NULL));
533}
#define PG_GETARG_TEXT_PP(n)
#define PG_GETARG_NAME(n)
#define PG_GET_COLLATION()
#define PG_RETURN_BOOL(x)
bool RE_compile_and_execute(text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
References NameStr, PG_GET_COLLATION, PG_GETARG_NAME, PG_GETARG_TEXT_PP, PG_RETURN_BOOL, RE_compile_and_execute(), REG_ADVANCED, and REG_ICASE.
◆ nameicregexne()
◆ nameregexeq()
◆ nameregexne()
◆ parse_re_flags()
Definition at line 385 of file regexp.c.
386{
387
389 flags->glob = false;
390
392 {
395 int i;
396
397 for (i = 0; i < opt_len; i++)
398 {
399 switch (opt_p[i])
400 {
401 case 'g':
402 flags->glob = true;
403 break;
404 case 'b':
406 break;
407 case 'c':
408 flags->cflags &= ~REG_ICASE;
409 break;
410 case 'e':
413 break;
414 case 'i':
416 break;
417 case 'm':
418 case 'n':
420 break;
421 case 'p':
423 flags->cflags &= ~REG_NLANCH;
424 break;
425 case 'q':
428 break;
429 case 's':
430 flags->cflags &= ~REG_NEWLINE;
431 break;
432 case 't':
433 flags->cflags &= ~REG_EXPANDED;
434 break;
435 case 'w':
436 flags->cflags &= ~REG_NLSTOP;
438 break;
439 case 'x':
441 break;
442 default:
444 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
445 errmsg("invalid regular expression option: \"%.*s\"",
447 break;
448 }
449 }
450 }
451}
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int pg_mblen(const char *mbstr)
static AmcheckOptions opts
#define VARSIZE_ANY_EXHDR(PTR)
References pg_re_flags::cflags, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, i, opts, pg_mblen(), REG_ADVANCED, REG_EXPANDED, REG_EXTENDED, REG_ICASE, REG_NEWLINE, REG_NLANCH, REG_NLSTOP, REG_QUOTE, VARDATA_ANY, and VARSIZE_ANY_EXHDR.
Referenced by regexp_count(), regexp_instr(), regexp_like(), regexp_match(), regexp_matches(), regexp_split_to_array(), regexp_split_to_table(), regexp_substr(), textregexreplace(), and textregexreplace_extended().
◆ RE_compile_and_cache()
regex_t * RE_compile_and_cache | ( | text * | text_re, |
---|---|---|---|
int | cflags, | ||
Oid | collation | ||
) |
Definition at line 141 of file regexp.c.
142{
144 char *text_re_val = VARDATA_ANY(text_re);
146 int pattern_len;
147 int i;
148 int regcomp_result;
150 char errMsg[100];
152
153
154
155
156
157
159 {
160 if (re_array[i].cre_pat_len == text_re_len &&
161 re_array[i].cre_flags == cflags &&
162 re_array[i].cre_collation == collation &&
163 memcmp(re_array[i].cre_pat, text_re_val, text_re_len) == 0)
164 {
165
166
167
168 if (i > 0)
169 {
173 }
174
176 }
177 }
178
179
183 "RegexpCacheMemoryContext",
185
186
187
188
189
190
191
194 pattern,
195 text_re_len);
196
197
198
199
200
201
202
203
205 "RegexpMemoryContext",
208
210 pattern,
211 pattern_len,
212 cflags,
213 collation);
214
216
217 if (regcomp_result != REG_OKAY)
218 {
219
220 pg_regerror(regcomp_result, &re_temp.cre_re, errMsg, sizeof(errMsg));
222 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
223 errmsg("invalid regular expression: %s", errMsg)));
224 }
225
226
228 memcpy(re_temp.cre_pat, text_re_val, text_re_len);
229
230
231
232
233
234 re_temp.cre_pat[text_re_len] = 0;
236
240
241
242
243
244
246 {
249
251 }
252
253
255
258
261
263
265}
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
void pfree(void *pointer)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
static MemoryContext RegexpCacheMemoryContext
static cached_re_str re_array[MAX_CACHED_RES]
MemoryContext cre_context
References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert(), cached_re_str::cre_collation, cached_re_str::cre_context, cached_re_str::cre_flags, cached_re_str::cre_pat, cached_re_str::cre_pat_len, cached_re_str::cre_re, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, i, MAX_CACHED_RES, MemoryContextDelete(), MemoryContextSetIdentifier(), MemoryContextSetParent(), MemoryContextSwitchTo(), num_res, palloc(), pfree(), pg_mb2wchar_with_len(), pg_regcomp(), pg_regerror(), re_array, REG_OKAY, RegexpCacheMemoryContext, TopMemoryContext, unlikely, VARDATA_ANY, and VARSIZE_ANY_EXHDR.
Referenced by RE_compile_and_execute(), regexp_fixed_prefix(), replace_text_regexp(), setup_regexp_matches(), and textregexsubstr().
◆ RE_compile_and_execute()
bool RE_compile_and_execute | ( | text * | text_re, |
---|---|---|---|
char * | dat, | ||
int | dat_len, | ||
int | cflags, | ||
Oid | collation, | ||
int | nmatch, | ||
regmatch_t * | pmatch | ||
) |
Definition at line 358 of file regexp.c.
361{
363
364
365 if (nmatch < 2)
367
368
370
371 return RE_execute(re, dat, dat_len, nmatch, pmatch);
372}
regex_t * RE_compile_and_cache(text *text_re, int cflags, Oid collation)
static bool RE_execute(regex_t *re, char *dat, int dat_len, int nmatch, regmatch_t *pmatch)
References RE_compile_and_cache(), RE_execute(), REG_NOSUB, and regex_t.
Referenced by executeLikeRegex(), nameicregexeq(), nameicregexne(), nameregexeq(), nameregexne(), regexp_like(), texticregexeq(), texticregexne(), textregexeq(), and textregexne().
◆ RE_execute()
static bool RE_execute ( regex_t * re, char * dat, int dat_len, int nmatch, regmatch_t * pmatch ) | static |
---|
Definition at line 324 of file regexp.c.
326{
328 int data_len;
329 bool match;
330
331
334
335
337
339 return match;
340}
static bool RE_wchar_execute(regex_t *re, pg_wchar *data, int data_len, int start_search, int nmatch, regmatch_t *pmatch)
References data, palloc(), pfree(), pg_mb2wchar_with_len(), and RE_wchar_execute().
Referenced by RE_compile_and_execute(), and textregexsubstr().
◆ RE_wchar_execute()
static bool RE_wchar_execute ( regex_t * re, pg_wchar * data, int data_len, int start_search, int nmatch, regmatch_t * pmatch ) | static |
---|
Definition at line 282 of file regexp.c.
284{
285 int regexec_result;
286 char errMsg[100];
287
288
291 data_len,
292 start_search,
293 NULL,
294 nmatch,
295 pmatch,
296 0);
297
299 {
300
301 pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
303 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
304 errmsg("regular expression failed: %s", errMsg)));
305 }
306
307 return (regexec_result == REG_OKAY);
308}
int pg_regexec(regex_t *re, const chr *string, size_t len, size_t search_start, rm_detail_t *details, size_t nmatch, regmatch_t pmatch[], int flags)
References data, ereport, errcode(), errmsg(), ERROR, pg_regerror(), pg_regexec(), REG_NOMATCH, and REG_OKAY.
Referenced by RE_execute(), and setup_regexp_matches().
◆ regexp_count()
Definition at line 1066 of file regexp.c.
1067{
1074
1075
1077 {
1081 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1082 errmsg("invalid value for parameter \"%s\": %d",
1083 "start", start)));
1084 }
1085
1086
1088
1089 if (re_flags.glob)
1091 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1092
1093 errmsg("%s does not support the \"global\" option",
1094 "regexp_count()")));
1095
1096 re_flags.glob = true;
1097
1098
1101 false,
1102 false, false);
1103
1105}
#define PG_RETURN_INT32(x)
#define PG_GETARG_INT32(n)
static regexp_matches_ctx * setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags, int start_search, Oid collation, bool use_subpatterns, bool ignore_degenerate, bool fetching_unmatched)
#define PG_GETARG_TEXT_PP_IF_EXISTS(_n)
static void parse_re_flags(pg_re_flags *flags, text *opts)
References ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, regexp_matches_ctx::nmatches, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_NARGS, PG_RETURN_INT32, setup_regexp_matches(), start, and str.
Referenced by regexp_count_no_flags(), and regexp_count_no_start().
◆ regexp_count_no_flags()
◆ regexp_count_no_start()
◆ regexp_fixed_prefix()
char * regexp_fixed_prefix | ( | text * | text_re, |
---|---|---|---|
bool | case_insensitive, | ||
Oid | collation, | ||
bool * | exact | ||
) |
Definition at line 1953 of file regexp.c.
1955{
1956 char *result;
1958 int cflags;
1959 int re_result;
1961 size_t slen;
1962 size_t maxlen;
1963 char errMsg[100];
1964
1965 *exact = false;
1966
1967
1969 if (case_insensitive)
1971
1973
1974
1976
1977 switch (re_result)
1978 {
1980 return NULL;
1981
1983
1984 break;
1985
1987 *exact = true;
1988
1989 break;
1990
1991 default:
1992
1993 pg_regerror(re_result, re, errMsg, sizeof(errMsg));
1995 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1996 errmsg("regular expression failed: %s", errMsg)));
1997 break;
1998 }
1999
2000
2002 result = (char *) palloc(maxlen);
2004 Assert(slen < maxlen);
2005
2007
2008 return result;
2009}
int pg_database_encoding_max_length(void)
int pg_regprefix(regex_t *re, chr **string, size_t *slength)
References Assert(), ereport, errcode(), errmsg(), ERROR, palloc(), pfree(), pg_database_encoding_max_length(), pg_regerror(), pg_regprefix(), pg_wchar2mb_with_len(), RE_compile_and_cache(), REG_ADVANCED, REG_EXACT, REG_ICASE, REG_NOMATCH, REG_NOSUB, REG_PREFIX, regex_t, and str.
Referenced by regex_fixed_prefix().
◆ regexp_instr()
Definition at line 1126 of file regexp.c.
1127{
1131 int n = 1;
1132 int endoption = 0;
1134 int subexpr = 0;
1135 int pos;
1138
1139
1141 {
1145 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1146 errmsg("invalid value for parameter \"%s\": %d",
1147 "start", start)));
1148 }
1150 {
1152 if (n <= 0)
1154 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1155 errmsg("invalid value for parameter \"%s\": %d",
1156 "n", n)));
1157 }
1159 {
1161 if (endoption != 0 && endoption != 1)
1163 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1164 errmsg("invalid value for parameter \"%s\": %d",
1165 "endoption", endoption)));
1166 }
1168 {
1170 if (subexpr < 0)
1172 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1173 errmsg("invalid value for parameter \"%s\": %d",
1174 "subexpr", subexpr)));
1175 }
1176
1177
1179
1180 if (re_flags.glob)
1182 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1183
1184 errmsg("%s does not support the \"global\" option",
1185 "regexp_instr()")));
1186
1187 re_flags.glob = true;
1188
1189
1192 (subexpr > 0),
1193 false, false);
1194
1195
1198
1199
1200 if (subexpr > matchctx->npatterns)
1202
1203
1204 pos = (n - 1) * matchctx->npatterns;
1205 if (subexpr > 0)
1206 pos += subexpr - 1;
1207 pos *= 2;
1208 if (endoption == 1)
1209 pos += 1;
1210
1213 else
1215}
if(TABLE==NULL||TABLE_index==NULL)
References ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, if(), regexp_matches_ctx::match_locs, regexp_matches_ctx::nmatches, regexp_matches_ctx::npatterns, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_NARGS, PG_RETURN_INT32, setup_regexp_matches(), start, and str.
Referenced by regexp_instr_no_endoption(), regexp_instr_no_flags(), regexp_instr_no_n(), regexp_instr_no_start(), and regexp_instr_no_subexpr().
◆ regexp_instr_no_endoption()
◆ regexp_instr_no_flags()
◆ regexp_instr_no_n()
◆ regexp_instr_no_start()
◆ regexp_instr_no_subexpr()
◆ regexp_like()
Definition at line 1257 of file regexp.c.
1258{
1263
1264
1266
1267 if (re_flags.glob)
1269 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1270
1271 errmsg("%s does not support the \"global\" option",
1272 "regexp_like()")));
1273
1274
1280 0, NULL));
1281}
References pg_re_flags::cflags, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_RETURN_BOOL, RE_compile_and_execute(), str, VARDATA_ANY, and VARSIZE_ANY_EXHDR.
Referenced by regexp_like_no_flags().
◆ regexp_like_no_flags()
◆ regexp_match()
Definition at line 1295 of file regexp.c.
1296{
1302
1303
1305
1306 if (re_flags.glob)
1308 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1309
1310 errmsg("%s does not support the \"global\" option",
1311 "regexp_match()"),
1312 errhint("Use the regexp_matches function instead.")));
1313
1316
1317 if (matchctx->nmatches == 0)
1319
1321
1322
1325
1327}
int errhint(const char *fmt,...)
#define PG_RETURN_DATUM(x)
static ArrayType * build_regexp_match_result(regexp_matches_ctx *matchctx)
References Assert(), build_regexp_match_result(), regexp_matches_ctx::elems, ereport, errcode(), errhint(), errmsg(), ERROR, pg_re_flags::glob, regexp_matches_ctx::nmatches, regexp_matches_ctx::npatterns, regexp_matches_ctx::nulls, palloc(), parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_RETURN_DATUM, PG_RETURN_NULL, PointerGetDatum(), and setup_regexp_matches().
Referenced by regexp_match_no_flags().
◆ regexp_match_no_flags()
◆ regexp_matches()
Definition at line 1341 of file regexp.c.
1342{
1345
1347 {
1352
1355
1356
1358
1359
1361 &re_flags, 0,
1363 true, false, false);
1364
1365
1368
1371 }
1372
1375
1377 {
1379
1383 }
1384
1386}
#define PG_GETARG_TEXT_P_COPY(n)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
#define SRF_RETURN_DONE(_funcctx)
MemoryContext multi_call_memory_ctx
References build_regexp_match_result(), regexp_matches_ctx::elems, if(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, regexp_matches_ctx::next_match, regexp_matches_ctx::nmatches, regexp_matches_ctx::npatterns, regexp_matches_ctx::nulls, palloc(), parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_P_COPY, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PointerGetDatum(), setup_regexp_matches(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.
Referenced by regexp_matches_no_flags().
◆ regexp_matches_no_flags()
◆ regexp_split_to_array()
Definition at line 1740 of file regexp.c.
1741{
1745
1746
1748
1749 if (re_flags.glob)
1751 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1752
1753 errmsg("%s does not support the \"global\" option",
1754 "regexp_split_to_array()")));
1755
1756 re_flags.glob = true;
1757
1760 &re_flags, 0,
1762 false, true, true);
1763
1765 {
1768 false,
1769 TEXTOID,
1772 }
1773
1775}
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
static Datum build_regexp_split_result(regexp_matches_ctx *splitctx)
References accumArrayResult(), build_regexp_split_result(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, makeArrayResult(), regexp_matches_ctx::next_match, regexp_matches_ctx::nmatches, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_RETURN_DATUM, and setup_regexp_matches().
Referenced by regexp_split_to_array_no_flags().
◆ regexp_split_to_array_no_flags()
◆ regexp_split_to_table()
Definition at line 1676 of file regexp.c.
1677{
1680
1682 {
1687
1690
1691
1693
1694 if (re_flags.glob)
1696 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1697
1698 errmsg("%s does not support the \"global\" option",
1699 "regexp_split_to_table()")));
1700
1701 re_flags.glob = true;
1702
1703
1705 &re_flags, 0,
1707 false, true, true);
1708
1711 }
1712
1715
1717 {
1719
1722 }
1723
1725}
References build_regexp_split_result(), ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, if(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, regexp_matches_ctx::next_match, regexp_matches_ctx::nmatches, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_P_COPY, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, setup_regexp_matches(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.
Referenced by regexp_split_to_table_no_flags().
◆ regexp_split_to_table_no_flags()
◆ regexp_substr()
Definition at line 1832 of file regexp.c.
1833{
1837 int n = 1;
1839 int subexpr = 0;
1840 int so,
1841 eo,
1842 pos;
1845
1846
1848 {
1852 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1853 errmsg("invalid value for parameter \"%s\": %d",
1854 "start", start)));
1855 }
1857 {
1859 if (n <= 0)
1861 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1862 errmsg("invalid value for parameter \"%s\": %d",
1863 "n", n)));
1864 }
1866 {
1868 if (subexpr < 0)
1870 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1871 errmsg("invalid value for parameter \"%s\": %d",
1872 "subexpr", subexpr)));
1873 }
1874
1875
1877
1878 if (re_flags.glob)
1880 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1881
1882 errmsg("%s does not support the \"global\" option",
1883 "regexp_substr()")));
1884
1885 re_flags.glob = true;
1886
1887
1890 (subexpr > 0),
1891 false, false);
1892
1893
1896
1897
1898 if (subexpr > matchctx->npatterns)
1900
1901
1902 pos = (n - 1) * matchctx->npatterns;
1903 if (subexpr > 0)
1904 pos += subexpr - 1;
1905 pos *= 2;
1908
1909 if (so < 0 || eo < 0)
1911
1916}
References DirectFunctionCall3, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, if(), Int32GetDatum(), regexp_matches_ctx::match_locs, regexp_matches_ctx::nmatches, regexp_matches_ctx::npatterns, regexp_matches_ctx::orig_str, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_NARGS, PG_RETURN_DATUM, PG_RETURN_NULL, PointerGetDatum(), setup_regexp_matches(), start, str, and text_substr().
Referenced by regexp_substr_no_flags(), regexp_substr_no_n(), regexp_substr_no_start(), and regexp_substr_no_subexpr().
◆ regexp_substr_no_flags()
◆ regexp_substr_no_n()
◆ regexp_substr_no_start()
◆ regexp_substr_no_subexpr()
◆ setup_regexp_matches()
static regexp_matches_ctx * setup_regexp_matches ( text * orig_str, text * pattern, pg_re_flags * re_flags, int start_search, Oid collation, bool use_subpatterns, bool ignore_degenerate, bool fetching_unmatched ) | static |
---|
Definition at line 1416 of file regexp.c.
1422{
1425 int orig_len;
1427 int wide_len;
1428 int cflags;
1431 int pmatch_len;
1432 int array_len;
1433 int array_idx;
1434 int prev_match_end;
1435 int prev_valid_match_end;
1436 int maxlen = 0;
1437
1438
1439 matchctx->orig_str = orig_str;
1440
1441
1445
1446
1447 cflags = re_flags->cflags;
1448 if (!use_subpatterns)
1451
1452
1453 if (use_subpatterns && cpattern->re_nsub > 0)
1454 {
1455 matchctx->npatterns = cpattern->re_nsub;
1456 pmatch_len = cpattern->re_nsub + 1;
1457 }
1458 else
1459 {
1460 use_subpatterns = false;
1462 pmatch_len = 1;
1463 }
1464
1465
1467
1468
1469
1470
1471
1472
1473
1474 array_len = re_flags->glob ? 255 : 31;
1475 matchctx->match_locs = (int *) palloc(sizeof(int) * array_len);
1476 array_idx = 0;
1477
1478
1479 prev_match_end = 0;
1480 prev_valid_match_end = 0;
1481 while (RE_wchar_execute(cpattern, wide_str, wide_len, start_search,
1482 pmatch_len, pmatch))
1483 {
1484
1485
1486
1487
1488
1489 if (!ignore_degenerate ||
1490 (pmatch[0].rm_so < wide_len &&
1491 pmatch[0].rm_eo > prev_match_end))
1492 {
1493
1494 while (array_idx + matchctx->npatterns * 2 + 1 > array_len)
1495 {
1496 array_len += array_len + 1;
1499 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1500 errmsg("too many regular expression matches")));
1502 sizeof(int) * array_len);
1503 }
1504
1505
1506 if (use_subpatterns)
1507 {
1508 int i;
1509
1511 {
1512 int so = pmatch[i].rm_so;
1513 int eo = pmatch[i].rm_eo;
1514
1515 matchctx->match_locs[array_idx++] = so;
1516 matchctx->match_locs[array_idx++] = eo;
1517 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1518 maxlen = (eo - so);
1519 }
1520 }
1521 else
1522 {
1523 int so = pmatch[0].rm_so;
1524 int eo = pmatch[0].rm_eo;
1525
1526 matchctx->match_locs[array_idx++] = so;
1527 matchctx->match_locs[array_idx++] = eo;
1528 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1529 maxlen = (eo - so);
1530 }
1532
1533
1534
1535
1536
1537
1538 if (fetching_unmatched &&
1539 pmatch[0].rm_so >= 0 &&
1540 (pmatch[0].rm_so - prev_valid_match_end) > maxlen)
1541 maxlen = (pmatch[0].rm_so - prev_valid_match_end);
1542 prev_valid_match_end = pmatch[0].rm_eo;
1543 }
1544 prev_match_end = pmatch[0].rm_eo;
1545
1546
1547 if (!re_flags->glob)
1548 break;
1549
1550
1551
1552
1553
1554
1555
1556 start_search = prev_match_end;
1557 if (pmatch[0].rm_so == pmatch[0].rm_eo)
1558 start_search++;
1559 if (start_search > wide_len)
1560 break;
1561 }
1562
1563
1564
1565
1566
1567 if (fetching_unmatched &&
1568 (wide_len - prev_valid_match_end) > maxlen)
1569 maxlen = (wide_len - prev_valid_match_end);
1570
1571
1572
1573
1574
1575 matchctx->match_locs[array_idx] = wide_len;
1576
1577 if (eml > 1)
1578 {
1579 int64 maxsiz = eml * (int64) maxlen;
1580 int conv_bufsiz;
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592 if (maxsiz > orig_len)
1593 conv_bufsiz = orig_len + 1;
1594 else
1595 conv_bufsiz = maxsiz + 1;
1596
1599 matchctx->wide_str = wide_str;
1600 }
1601 else
1602 {
1603
1604 pfree(wide_str);
1608 }
1609
1610
1612
1613 return matchctx;
1614}
void * repalloc(void *pointer, Size size)
void * palloc0(Size size)
References pg_re_flags::cflags, regexp_matches_ctx::conv_buf, regexp_matches_ctx::conv_bufsiz, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, i, regexp_matches_ctx::match_locs, MaxAllocSize, regexp_matches_ctx::nmatches, regexp_matches_ctx::npatterns, regexp_matches_ctx::orig_str, palloc(), palloc0(), pfree(), pg_database_encoding_max_length(), pg_mb2wchar_with_len(), RE_compile_and_cache(), RE_wchar_execute(), REG_NOSUB, regex_t, regmatch_t, repalloc(), VARDATA_ANY, VARSIZE_ANY_EXHDR, and regexp_matches_ctx::wide_str.
Referenced by regexp_count(), regexp_instr(), regexp_match(), regexp_matches(), regexp_split_to_array(), regexp_split_to_table(), and regexp_substr().
◆ similar_escape()
◆ similar_escape_internal()
static text * similar_escape_internal ( text * pat_text, text * esc_text ) | static |
---|
Definition at line 767 of file regexp.c.
768{
769 text *result;
770 char *p,
771 *e,
772 *r;
773 int plen,
774 elen;
775 bool afterescape = false;
776 bool incharclass = false;
777 int nquotes = 0;
778
781 if (esc_text == NULL)
782 {
783
784 e = "\\";
785 elen = 1;
786 }
787 else
788 {
791 if (elen == 0)
792 e = NULL;
793 else if (elen > 1)
794 {
796
797 if (escape_mblen > 1)
799 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
800 errmsg("invalid escape string"),
801 errhint("Escape string must be empty or one character.")));
802 }
803 }
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
846
847 *r++ = '^';
848 *r++ = '(';
849 *r++ = '?';
850 *r++ = ':';
851
852 while (plen > 0)
853 {
854 char pchar = *p;
855
856
857
858
859
860
861
862
863
864
865
866
867 if (elen > 1)
868 {
870
871 if (mblen > 1)
872 {
873
874 if (afterescape)
875 {
876 *r++ = '\\';
877 memcpy(r, p, mblen);
878 r += mblen;
879 afterescape = false;
880 }
881 else if (e && elen == mblen && memcmp(e, p, mblen) == 0)
882 {
883
884 afterescape = true;
885 }
886 else
887 {
888
889
890
891
892
893 memcpy(r, p, mblen);
894 r += mblen;
895 }
896
897 p += mblen;
898 plen -= mblen;
899
900 continue;
901 }
902 }
903
904
905 if (afterescape)
906 {
907 if (pchar == '"' && !incharclass)
908 {
909
910 if (nquotes == 0)
911 {
912 *r++ = ')';
913 *r++ = '{';
914 *r++ = '1';
915 *r++ = ',';
916 *r++ = '1';
917 *r++ = '}';
918 *r++ = '?';
919 *r++ = '(';
920 }
921 else if (nquotes == 1)
922 {
923 *r++ = ')';
924 *r++ = '{';
925 *r++ = '1';
926 *r++ = ',';
927 *r++ = '1';
928 *r++ = '}';
929 *r++ = '(';
930 *r++ = '?';
931 *r++ = ':';
932 }
933 else
935 (errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER),
936 errmsg("SQL regular expression may not contain more than two escape-double-quote separators")));
937 nquotes++;
938 }
939 else
940 {
941
942
943
944
945
946 *r++ = '\\';
947 *r++ = pchar;
948 }
949 afterescape = false;
950 }
951 else if (e && pchar == *e)
952 {
953
954 afterescape = true;
955 }
956 else if (incharclass)
957 {
958 if (pchar == '\\')
959 *r++ = '\\';
960 *r++ = pchar;
961 if (pchar == ']')
962 incharclass = false;
963 }
964 else if (pchar == '[')
965 {
966 *r++ = pchar;
967 incharclass = true;
968 }
969 else if (pchar == '%')
970 {
971 *r++ = '.';
972 *r++ = '*';
973 }
974 else if (pchar == '_')
975 *r++ = '.';
976 else if (pchar == '(')
977 {
978
979 *r++ = '(';
980 *r++ = '?';
981 *r++ = ':';
982 }
983 else if (pchar == '\\' || pchar == '.' ||
984 pchar == '^' || pchar == '$')
985 {
986 *r++ = '\\';
987 *r++ = pchar;
988 }
989 else
990 *r++ = pchar;
991 p++, plen--;
992 }
993
994 *r++ = ')';
995 *r++ = '$';
996
997 SET_VARSIZE(result, r - ((char *) result));
998
999 return result;
1000}
int pg_mbstrlen_with_len(const char *mbstr, int limit)
#define SET_VARSIZE(PTR, len)
References ereport, errcode(), errhint(), errmsg(), ERROR, palloc(), pg_mblen(), pg_mbstrlen_with_len(), SET_VARSIZE, VARDATA, VARDATA_ANY, VARHDRSZ, and VARSIZE_ANY_EXHDR.
Referenced by similar_escape(), similar_to_escape_1(), and similar_to_escape_2().
◆ similar_to_escape_1()
◆ similar_to_escape_2()
◆ texticregexeq()
◆ texticregexne()
◆ textregexeq()
◆ textregexne()
◆ textregexreplace()
Definition at line 658 of file regexp.c.
659{
665
666
667
668
669
670
671
672
674 {
676
677 if (*opt_p >= '0' && *opt_p <= '9')
679 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
680 errmsg("invalid regular expression option: \"%.*s\"",
682 errhint("If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly.")));
683 }
684
686
689 0, flags.glob ? 0 : 1));
690}
text * replace_text_regexp(text *src_text, text *pattern_text, text *replace_text, int cflags, Oid collation, int search_start, int n)
References pg_re_flags::cflags, ereport, errcode(), errhint(), errmsg(), ERROR, pg_re_flags::glob, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_PP, pg_mblen(), PG_RETURN_TEXT_P, replace_text_regexp(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.
Referenced by execute_extension_script().
◆ textregexreplace_extended()
Definition at line 699 of file regexp.c.
700{
705 int n = 1;
708
709
711 {
715 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
716 errmsg("invalid value for parameter \"%s\": %d",
717 "start", start)));
718 }
720 {
722 if (n < 0)
724 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
725 errmsg("invalid value for parameter \"%s\": %d",
726 "n", n)));
727 }
728
729
731
732
734 n = re_flags.glob ? 0 : 1;
735
736
740}
References pg_re_flags::cflags, ereport, errcode(), errmsg(), ERROR, pg_re_flags::glob, parse_re_flags(), PG_GET_COLLATION, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_GETARG_TEXT_PP_IF_EXISTS, PG_NARGS, PG_RETURN_TEXT_P, replace_text_regexp(), and start.
Referenced by textregexreplace_extended_no_flags(), and textregexreplace_extended_no_n().
◆ textregexreplace_extended_no_flags()
◆ textregexreplace_extended_no_n()
◆ textregexreplace_noopt()
◆ textregexsubstr()
Definition at line 583 of file regexp.c.
584{
589 int so,
590 eo;
591
592
594
595
596
597
598
599
600
603 2, pmatch))
605
606 if (re->re_nsub > 0)
607 {
608
609 so = pmatch[1].rm_so;
610 eo = pmatch[1].rm_eo;
611 }
612 else
613 {
614
615 so = pmatch[0].rm_so;
616 eo = pmatch[0].rm_eo;
617 }
618
619
620
621
622
623
624
625 if (so < 0 || eo < 0)
627
632}
References DirectFunctionCall3, Int32GetDatum(), PG_GET_COLLATION, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PointerGetDatum(), RE_compile_and_cache(), RE_execute(), REG_ADVANCED, regex_t, regmatch_t, text_substr(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.