📄 regexp.c
字号:
VARDATA(s), VARSIZE(s) - VARHDRSZ, regex_flavor, 0, NULL));}Datumtextregexne(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, VARDATA(s), VARSIZE(s) - VARHDRSZ, regex_flavor, 0, NULL));}/* * routines that use the regexp stuff, but ignore the case. * for this, we use the REG_ICASE flag to pg_regcomp */Datumnameicregexeq(PG_FUNCTION_ARGS){ Name n = PG_GETARG_NAME(0); text *p = PG_GETARG_TEXT_P(1); PG_RETURN_BOOL(RE_compile_and_execute(p, NameStr(*n), strlen(NameStr(*n)), regex_flavor | REG_ICASE, 0, NULL));}Datumnameicregexne(PG_FUNCTION_ARGS){ Name n = PG_GETARG_NAME(0); text *p = PG_GETARG_TEXT_P(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, NameStr(*n), strlen(NameStr(*n)), regex_flavor | REG_ICASE, 0, NULL));}Datumtexticregexeq(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); PG_RETURN_BOOL(RE_compile_and_execute(p, VARDATA(s), VARSIZE(s) - VARHDRSZ, regex_flavor | REG_ICASE, 0, NULL));}Datumtexticregexne(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, VARDATA(s), VARSIZE(s) - VARHDRSZ, regex_flavor | REG_ICASE, 0, NULL));}/* * textregexsubstr() * Return a substring matched by a regular expression. */Datumtextregexsubstr(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); bool match; regmatch_t pmatch[2]; /* * We pass two regmatch_t structs to get info about the overall match and * the match for the first parenthesized subexpression (if any). If there * is a parenthesized subexpression, we return what it matched; else * return what the whole regexp matched. */ match = RE_compile_and_execute(p, VARDATA(s), VARSIZE(s) - VARHDRSZ, regex_flavor, 2, pmatch); /* match? then return the substring matching the pattern */ if (match) { int so, eo; so = pmatch[1].rm_so; eo = pmatch[1].rm_eo; if (so < 0 || eo < 0) { /* no parenthesized subexpression */ so = pmatch[0].rm_so; eo = pmatch[0].rm_eo; } return DirectFunctionCall3(text_substr, PointerGetDatum(s), Int32GetDatum(so + 1), Int32GetDatum(eo - so)); } PG_RETURN_NULL();}/* * textregexreplace_noopt() * Return a string matched by a regular expression, with replacement. * * This version doesn't have an option argument: we default to case * sensitive match, replace the first instance only. */Datumtextregexreplace_noopt(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); text *r = PG_GETARG_TEXT_P(2); regex_t *re; re = RE_compile_and_cache(p, regex_flavor); PG_RETURN_TEXT_P(replace_text_regexp(s, (void *) re, r, false));}/* * textregexreplace() * Return a string matched by a regular expression, with replacement. */Datumtextregexreplace(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); text *p = PG_GETARG_TEXT_P(1); text *r = PG_GETARG_TEXT_P(2); text *opt = PG_GETARG_TEXT_P(3); char *opt_p = VARDATA(opt); int opt_len = (VARSIZE(opt) - VARHDRSZ); int i; bool glob = false; bool ignorecase = false; regex_t *re; /* parse options */ for (i = 0; i < opt_len; i++) { switch (opt_p[i]) { case 'i': ignorecase = true; break; case 'g': glob = true; break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid option of regexp_replace: %c", opt_p[i]))); break; } } if (ignorecase) re = RE_compile_and_cache(p, regex_flavor | REG_ICASE); else re = RE_compile_and_cache(p, regex_flavor); PG_RETURN_TEXT_P(replace_text_regexp(s, (void *) re, r, glob));}/* similar_escape() * Convert a SQL99 regexp pattern to POSIX style, so it can be used by * our regexp engine. */Datumsimilar_escape(PG_FUNCTION_ARGS){ text *pat_text; text *esc_text; text *result; char *p, *e, *r; int plen, elen; bool afterescape = false; int nquotes = 0; /* This function is not strict, so must test explicitly */ if (PG_ARGISNULL(0)) PG_RETURN_NULL(); pat_text = PG_GETARG_TEXT_P(0); p = VARDATA(pat_text); plen = (VARSIZE(pat_text) - VARHDRSZ); if (PG_ARGISNULL(1)) { /* No ESCAPE clause provided; default to backslash as escape */ e = "\\"; elen = 1; } else { esc_text = PG_GETARG_TEXT_P(1); e = VARDATA(esc_text); elen = (VARSIZE(esc_text) - VARHDRSZ); if (elen == 0) e = NULL; /* no escape character */ else if (elen != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), errmsg("invalid escape string"), errhint("Escape string must be empty or one character."))); } /*---------- * We surround the transformed input string with * ***:^(?: ... )$ * which is bizarre enough to require some explanation. "***:" is a * director prefix to force the regex to be treated as an ARE regardless * of the current regex_flavor setting. We need "^" and "$" to force * the pattern to match the entire input string as per SQL99 spec. The * "(?:" and ")" are a non-capturing set of parens; we have to have * parens in case the string contains "|", else the "^" and "$" will * be bound into the first and last alternatives which is not what we * want, and the parens must be non capturing because we don't want them * to count when selecting output for SUBSTRING. *---------- */ /* * We need room for the prefix/postfix plus as many as 2 output bytes per * input byte */ result = (text *) palloc(VARHDRSZ + 10 + 2 * plen); r = VARDATA(result); *r++ = '*'; *r++ = '*'; *r++ = '*'; *r++ = ':'; *r++ = '^'; *r++ = '('; *r++ = '?'; *r++ = ':'; while (plen > 0) { char pchar = *p; if (afterescape) { if (pchar == '"') /* for SUBSTRING patterns */ *r++ = ((nquotes++ % 2) == 0) ? '(' : ')'; else { *r++ = '\\'; *r++ = pchar; } afterescape = false; } else if (e && pchar == *e) { /* SQL99 escape character; do not send to output */ afterescape = true; } else if (pchar == '%') { *r++ = '.'; *r++ = '*'; } else if (pchar == '_') *r++ = '.'; else if (pchar == '\\' || pchar == '.' || pchar == '?' || pchar == '{') { *r++ = '\\'; *r++ = pchar; } else *r++ = pchar; p++, plen--; } *r++ = ')'; *r++ = '$'; VARATT_SIZEP(result) = r - ((char *) result); PG_RETURN_TEXT_P(result);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -