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
Functions
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 ArrayType * build_regexp_match_result (regexp_matches_ctx *matchctx)
static Datum build_regexp_split_result (regexp_matches_ctx *splitctx)
regex_t * RE_compile_and_cache (text *text_re, int cflags, Oid collation)
static bool RE_wchar_execute (regex_t *re, pg_wchar *data, int data_len, int start_search, int nmatch, regmatch_t *pmatch)
static bool RE_execute (regex_t *re, char *dat, int dat_len, int nmatch, regmatch_t *pmatch)
bool RE_compile_and_execute (text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
static void parse_re_flags (pg_re_flags *flags, text *opts)
Datum nameregexeq (PG_FUNCTION_ARGS)
Datum nameregexne (PG_FUNCTION_ARGS)
Datum textregexeq (PG_FUNCTION_ARGS)
Datum textregexne (PG_FUNCTION_ARGS)
Datum nameicregexeq (PG_FUNCTION_ARGS)
Datum nameicregexne (PG_FUNCTION_ARGS)
Datum texticregexeq (PG_FUNCTION_ARGS)
Datum texticregexne (PG_FUNCTION_ARGS)
Datum textregexsubstr (PG_FUNCTION_ARGS)
Datum textregexreplace_noopt (PG_FUNCTION_ARGS)
Datum textregexreplace (PG_FUNCTION_ARGS)
Datum textregexreplace_extended (PG_FUNCTION_ARGS)
Datum textregexreplace_extended_no_n (PG_FUNCTION_ARGS)
Datum textregexreplace_extended_no_flags (PG_FUNCTION_ARGS)
static text * similar_escape_internal (text *pat_text, text *esc_text)
Datum similar_to_escape_2 (PG_FUNCTION_ARGS)
Datum similar_to_escape_1 (PG_FUNCTION_ARGS)
Datum similar_escape (PG_FUNCTION_ARGS)
Datum regexp_count (PG_FUNCTION_ARGS)
Datum regexp_count_no_start (PG_FUNCTION_ARGS)
Datum regexp_count_no_flags (PG_FUNCTION_ARGS)
Datum regexp_instr (PG_FUNCTION_ARGS)
Datum regexp_instr_no_start (PG_FUNCTION_ARGS)
Datum regexp_instr_no_n (PG_FUNCTION_ARGS)
Datum regexp_instr_no_endoption (PG_FUNCTION_ARGS)
Datum regexp_instr_no_flags (PG_FUNCTION_ARGS)
Datum regexp_instr_no_subexpr (PG_FUNCTION_ARGS)
Datum regexp_like (PG_FUNCTION_ARGS)
Datum regexp_like_no_flags (PG_FUNCTION_ARGS)
Datum regexp_match (PG_FUNCTION_ARGS)
Datum regexp_match_no_flags (PG_FUNCTION_ARGS)
Datum regexp_matches (PG_FUNCTION_ARGS)
Datum regexp_matches_no_flags (PG_FUNCTION_ARGS)
Datum regexp_split_to_table (PG_FUNCTION_ARGS)
Datum regexp_split_to_table_no_flags (PG_FUNCTION_ARGS)
Datum regexp_split_to_array (PG_FUNCTION_ARGS)
Datum regexp_split_to_array_no_flags (PG_FUNCTION_ARGS)
Datum regexp_substr (PG_FUNCTION_ARGS)
Datum regexp_substr_no_start (PG_FUNCTION_ARGS)
Datum regexp_substr_no_n (PG_FUNCTION_ARGS)
Datum regexp_substr_no_flags (PG_FUNCTION_ARGS)
Datum regexp_substr_no_subexpr (PG_FUNCTION_ARGS)
char * regexp_fixed_prefix (text *text_re, bool case_insensitive, Oid collation, bool *exact)
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 {

1708 elems[i] = (Datum) 0;

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().

num_res

re_array

RegexpCacheMemoryContext