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 1689 of file regexp.c.
1690{
1693 bool *nulls = matchctx->nulls;
1694 int dims[1];
1695 int lbs[1];
1696 int loc;
1697 int i;
1698
1699
1702 {
1703 int so = matchctx->match_locs[loc++];
1704 int eo = matchctx->match_locs[loc++];
1705
1706 if (so < 0 || eo < 0)
1707 {
1709 nulls[i] = true;
1710 }
1711 else if (buf)
1712 {
1715 eo - so);
1716
1717 Assert(len < matchctx->conv_bufsiz);
1719 nulls[i] = false;
1720 }
1721 else
1722 {
1727 nulls[i] = false;
1728 }
1729 }
1730
1731
1733 lbs[0] = 1;
1734
1736 TEXTOID, -1, false, TYPALIGN_INT);
1737}
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 char buf[DEFAULT_XLOG_SEG_SIZE]
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 1860 of file regexp.c.
1861{
1865
1868 else
1871 elog(ERROR, "invalid match ending position");
1872
1875 elog(ERROR, "invalid match starting position");
1876
1877 if (buf)
1878 {
1879 int len;
1880
1884 Assert(len < splitctx->conv_bufsiz);
1886 }
1887 else
1888 {
1893 }
1894}
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
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static char * VARDATA_ANY(const void *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}
#define palloc_array(type, count)
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(), palloc_array, 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_array, 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 1135 of file regexp.c.
1136{
1143
1144
1146 {
1150 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1151 errmsg("invalid value for parameter \"%s\": %d",
1152 "start", start)));
1153 }
1154
1155
1157
1158 if (re_flags.glob)
1160 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1161
1162 errmsg("%s does not support the \"global\" option",
1163 "regexp_count()")));
1164
1165 re_flags.glob = true;
1166
1167
1170 false,
1171 false, false);
1172
1174}
#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 2022 of file regexp.c.
2024{
2025 char *result;
2027 int cflags;
2028 int re_result;
2030 size_t slen;
2031 size_t maxlen;
2032 char errMsg[100];
2033
2034 *exact = false;
2035
2036
2038 if (case_insensitive)
2040
2042
2043
2045
2046 switch (re_result)
2047 {
2049 return NULL;
2050
2052
2053 break;
2054
2056 *exact = true;
2057
2058 break;
2059
2060 default:
2061
2062 pg_regerror(re_result, re, errMsg, sizeof(errMsg));
2064 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2065 errmsg("regular expression failed: %s", errMsg)));
2066 break;
2067 }
2068
2069
2071 result = (char *) palloc(maxlen);
2073 Assert(slen < maxlen);
2074
2076
2077 return result;
2078}
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 1195 of file regexp.c.
1196{
1200 int n = 1;
1201 int endoption = 0;
1203 int subexpr = 0;
1204 int pos;
1207
1208
1210 {
1214 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1215 errmsg("invalid value for parameter \"%s\": %d",
1216 "start", start)));
1217 }
1219 {
1221 if (n <= 0)
1223 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1224 errmsg("invalid value for parameter \"%s\": %d",
1225 "n", n)));
1226 }
1228 {
1230 if (endoption != 0 && endoption != 1)
1232 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1233 errmsg("invalid value for parameter \"%s\": %d",
1234 "endoption", endoption)));
1235 }
1237 {
1239 if (subexpr < 0)
1241 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1242 errmsg("invalid value for parameter \"%s\": %d",
1243 "subexpr", subexpr)));
1244 }
1245
1246
1248
1249 if (re_flags.glob)
1251 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1252
1253 errmsg("%s does not support the \"global\" option",
1254 "regexp_instr()")));
1255
1256 re_flags.glob = true;
1257
1258
1261 (subexpr > 0),
1262 false, false);
1263
1264
1267
1268
1269 if (subexpr > matchctx->npatterns)
1271
1272
1273 pos = (n - 1) * matchctx->npatterns;
1274 if (subexpr > 0)
1275 pos += subexpr - 1;
1276 pos *= 2;
1277 if (endoption == 1)
1278 pos += 1;
1279
1282 else
1284}
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 1326 of file regexp.c.
1327{
1332
1333
1335
1336 if (re_flags.glob)
1338 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1339
1340 errmsg("%s does not support the \"global\" option",
1341 "regexp_like()")));
1342
1343
1349 0, NULL));
1350}
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 1364 of file regexp.c.
1365{
1371
1372
1374
1375 if (re_flags.glob)
1377 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1378
1379 errmsg("%s does not support the \"global\" option",
1380 "regexp_match()"),
1381 errhint("Use the regexp_matches function instead.")));
1382
1385
1386 if (matchctx->nmatches == 0)
1388
1390
1391
1394
1396}
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_array, 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 1410 of file regexp.c.
1411{
1414
1416 {
1421
1424
1425
1427
1428
1430 &re_flags, 0,
1432 true, false, false);
1433
1434
1437
1440 }
1441
1444
1446 {
1448
1452 }
1453
1455}
#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_array, 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 1809 of file regexp.c.
1810{
1814
1815
1817
1818 if (re_flags.glob)
1820 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1821
1822 errmsg("%s does not support the \"global\" option",
1823 "regexp_split_to_array()")));
1824
1825 re_flags.glob = true;
1826
1829 &re_flags, 0,
1831 false, true, true);
1832
1834 {
1837 false,
1838 TEXTOID,
1841 }
1842
1844}
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 1745 of file regexp.c.
1746{
1749
1751 {
1756
1759
1760
1762
1763 if (re_flags.glob)
1765 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1766
1767 errmsg("%s does not support the \"global\" option",
1768 "regexp_split_to_table()")));
1769
1770 re_flags.glob = true;
1771
1772
1774 &re_flags, 0,
1776 false, true, true);
1777
1780 }
1781
1784
1786 {
1788
1791 }
1792
1794}
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 1901 of file regexp.c.
1902{
1906 int n = 1;
1908 int subexpr = 0;
1909 int so,
1910 eo,
1911 pos;
1914
1915
1917 {
1921 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1922 errmsg("invalid value for parameter \"%s\": %d",
1923 "start", start)));
1924 }
1926 {
1928 if (n <= 0)
1930 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1931 errmsg("invalid value for parameter \"%s\": %d",
1932 "n", n)));
1933 }
1935 {
1937 if (subexpr < 0)
1939 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1940 errmsg("invalid value for parameter \"%s\": %d",
1941 "subexpr", subexpr)));
1942 }
1943
1944
1946
1947 if (re_flags.glob)
1949 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1950
1951 errmsg("%s does not support the \"global\" option",
1952 "regexp_substr()")));
1953
1954 re_flags.glob = true;
1955
1956
1959 (subexpr > 0),
1960 false, false);
1961
1962
1965
1966
1967 if (subexpr > matchctx->npatterns)
1969
1970
1971 pos = (n - 1) * matchctx->npatterns;
1972 if (subexpr > 0)
1973 pos += subexpr - 1;
1974 pos *= 2;
1977
1978 if (so < 0 || eo < 0)
1980
1985}
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 1485 of file regexp.c.
1491{
1494 int orig_len;
1496 int wide_len;
1497 int cflags;
1500 int pmatch_len;
1501 int array_len;
1502 int array_idx;
1503 int prev_match_end;
1504 int prev_valid_match_end;
1505 int maxlen = 0;
1506
1507
1508 matchctx->orig_str = orig_str;
1509
1510
1514
1515
1516 cflags = re_flags->cflags;
1517 if (!use_subpatterns)
1520
1521
1522 if (use_subpatterns && cpattern->re_nsub > 0)
1523 {
1524 matchctx->npatterns = cpattern->re_nsub;
1525 pmatch_len = cpattern->re_nsub + 1;
1526 }
1527 else
1528 {
1529 use_subpatterns = false;
1531 pmatch_len = 1;
1532 }
1533
1534
1536
1537
1538
1539
1540
1541
1542
1543 array_len = re_flags->glob ? 255 : 31;
1545 array_idx = 0;
1546
1547
1548 prev_match_end = 0;
1549 prev_valid_match_end = 0;
1550 while (RE_wchar_execute(cpattern, wide_str, wide_len, start_search,
1551 pmatch_len, pmatch))
1552 {
1553
1554
1555
1556
1557
1558 if (!ignore_degenerate ||
1559 (pmatch[0].rm_so < wide_len &&
1560 pmatch[0].rm_eo > prev_match_end))
1561 {
1562
1563 while (array_idx + matchctx->npatterns * 2 + 1 > array_len)
1564 {
1565 array_len += array_len + 1;
1568 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1569 errmsg("too many regular expression matches")));
1571 sizeof(int) * array_len);
1572 }
1573
1574
1575 if (use_subpatterns)
1576 {
1577 int i;
1578
1580 {
1581 int so = pmatch[i].rm_so;
1582 int eo = pmatch[i].rm_eo;
1583
1584 matchctx->match_locs[array_idx++] = so;
1585 matchctx->match_locs[array_idx++] = eo;
1586 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1587 maxlen = (eo - so);
1588 }
1589 }
1590 else
1591 {
1592 int so = pmatch[0].rm_so;
1593 int eo = pmatch[0].rm_eo;
1594
1595 matchctx->match_locs[array_idx++] = so;
1596 matchctx->match_locs[array_idx++] = eo;
1597 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1598 maxlen = (eo - so);
1599 }
1601
1602
1603
1604
1605
1606
1607 if (fetching_unmatched &&
1608 pmatch[0].rm_so >= 0 &&
1609 (pmatch[0].rm_so - prev_valid_match_end) > maxlen)
1610 maxlen = (pmatch[0].rm_so - prev_valid_match_end);
1611 prev_valid_match_end = pmatch[0].rm_eo;
1612 }
1613 prev_match_end = pmatch[0].rm_eo;
1614
1615
1616 if (!re_flags->glob)
1617 break;
1618
1619
1620
1621
1622
1623
1624
1625 start_search = prev_match_end;
1626 if (pmatch[0].rm_so == pmatch[0].rm_eo)
1627 start_search++;
1628 if (start_search > wide_len)
1629 break;
1630 }
1631
1632
1633
1634
1635
1636 if (fetching_unmatched &&
1637 (wide_len - prev_valid_match_end) > maxlen)
1638 maxlen = (wide_len - prev_valid_match_end);
1639
1640
1641
1642
1643
1644 matchctx->match_locs[array_idx] = wide_len;
1645
1646 if (eml > 1)
1647 {
1648 int64 maxsiz = eml * (int64) maxlen;
1649 int conv_bufsiz;
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661 if (maxsiz > orig_len)
1662 conv_bufsiz = orig_len + 1;
1663 else
1664 conv_bufsiz = maxsiz + 1;
1665
1668 matchctx->wide_str = wide_str;
1669 }
1670 else
1671 {
1672
1673 pfree(wide_str);
1677 }
1678
1679
1681
1682 return matchctx;
1683}
#define palloc0_object(type)
void * repalloc(void *pointer, 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_object, palloc_array, 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 int nquotes = 0;
777 int bracket_depth = 0;
778 int charclass_pos = 0;
779
782 if (esc_text == NULL)
783 {
784
785 e = "\\";
786 elen = 1;
787 }
788 else
789 {
792 if (elen == 0)
793 e = NULL;
794 else if (elen > 1)
795 {
797
798 if (escape_mblen > 1)
800 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
801 errmsg("invalid escape string"),
802 errhint("Escape string must be empty or one character.")));
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
844
845
846
847
848
849
850
851
852
853
854
855
858
859 *r++ = '^';
860 *r++ = '(';
861 *r++ = '?';
862 *r++ = ':';
863
864 while (plen > 0)
865 {
866 char pchar = *p;
867
868
869
870
871
872
873
874
875
876
877
878
879 if (elen > 1)
880 {
882
883 if (mblen > 1)
884 {
885
886 if (afterescape)
887 {
888 *r++ = '\\';
889 memcpy(r, p, mblen);
890 r += mblen;
891 afterescape = false;
892 }
893 else if (e && elen == mblen && memcmp(e, p, mblen) == 0)
894 {
895
896 afterescape = true;
897 }
898 else
899 {
900
901
902
903
904
905 memcpy(r, p, mblen);
906 r += mblen;
907 }
908
909 p += mblen;
910 plen -= mblen;
911
912 continue;
913 }
914 }
915
916
917 if (afterescape)
918 {
919 if (pchar == '"' && bracket_depth < 1)
920 {
921
922 if (nquotes == 0)
923 {
924 *r++ = ')';
925 *r++ = '{';
926 *r++ = '1';
927 *r++ = ',';
928 *r++ = '1';
929 *r++ = '}';
930 *r++ = '?';
931 *r++ = '(';
932 }
933 else if (nquotes == 1)
934 {
935 *r++ = ')';
936 *r++ = '{';
937 *r++ = '1';
938 *r++ = ',';
939 *r++ = '1';
940 *r++ = '}';
941 *r++ = '(';
942 *r++ = '?';
943 *r++ = ':';
944 }
945 else
947 (errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER),
948 errmsg("SQL regular expression may not contain more than two escape-double-quote separators")));
949 nquotes++;
950 }
951 else
952 {
953
954
955
956
957
958 *r++ = '\\';
959 *r++ = pchar;
960
961
962
963
964
965 charclass_pos = 3;
966 }
967 afterescape = false;
968 }
969 else if (e && pchar == *e)
970 {
971
972 afterescape = true;
973 }
974 else if (bracket_depth > 0)
975 {
976
977 if (pchar == '\\')
978 {
979
980
981
982
983
984
985 *r++ = '\\';
986 }
987 *r++ = pchar;
988
989
990 if (pchar == ']' && charclass_pos > 2)
991 {
992
993 bracket_depth--;
994
995 }
996 else if (pchar == '[')
997 {
998
999 bracket_depth++;
1000
1001
1002
1003
1004
1005
1006 charclass_pos = 3;
1007 }
1008 else if (pchar == '^')
1009 {
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 charclass_pos++;
1020 }
1021 else
1022 {
1023
1024
1025
1026
1027
1028 charclass_pos = 3;
1029 }
1030 }
1031 else if (pchar == '[')
1032 {
1033
1034 *r++ = pchar;
1035 bracket_depth = 1;
1036 charclass_pos = 1;
1037 }
1038 else if (pchar == '%')
1039 {
1040 *r++ = '.';
1041 *r++ = '*';
1042 }
1043 else if (pchar == '_')
1044 *r++ = '.';
1045 else if (pchar == '(')
1046 {
1047
1048 *r++ = '(';
1049 *r++ = '?';
1050 *r++ = ':';
1051 }
1052 else if (pchar == '\\' || pchar == '.' ||
1053 pchar == '^' || pchar == '$')
1054 {
1055 *r++ = '\\';
1056 *r++ = pchar;
1057 }
1058 else
1059 *r++ = pchar;
1060 p++, plen--;
1061 }
1062
1063 *r++ = ')';
1064 *r++ = '$';
1065
1066 SET_VARSIZE(result, r - ((char *) result));
1067
1068 return result;
1069}
int pg_mbstrlen_with_len(const char *mbstr, int limit)
static char * VARDATA(const void *PTR)
static void SET_VARSIZE(void *PTR, Size 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().