regexp.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,177 行 · 第 1/3 页
C
1,177 行
break; case 't': /* tight syntax */ flags->cflags &= ~REG_EXPANDED; break; case 'w': /* weird, \n affects ^ $ only */ flags->cflags &= ~REG_NLSTOP; flags->cflags |= REG_NLANCH; break; case 'x': /* expanded syntax */ flags->cflags |= REG_EXPANDED; break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid regexp option: \"%c\"", opt_p[i]))); break; } } }}/* * assign_regex_flavor - GUC hook to validate and set REGEX_FLAVOR */const char *assign_regex_flavor(const char *value, bool doit, GucSource source){ if (pg_strcasecmp(value, "advanced") == 0) { if (doit) regex_flavor = REG_ADVANCED; } else if (pg_strcasecmp(value, "extended") == 0) { if (doit) regex_flavor = REG_EXTENDED; } else if (pg_strcasecmp(value, "basic") == 0) { if (doit) regex_flavor = REG_BASIC; } else return NULL; /* fail */ return value; /* OK */}/* * report whether regex_flavor is currently BASIC */boolregex_flavor_is_basic(void){ return (regex_flavor == REG_BASIC);}/* * interface routines called by the function manager */Datumnameregexeq(PG_FUNCTION_ARGS){ Name n = PG_GETARG_NAME(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(RE_compile_and_execute(p, NameStr(*n), strlen(NameStr(*n)), regex_flavor, 0, NULL));}Datumnameregexne(PG_FUNCTION_ARGS){ Name n = PG_GETARG_NAME(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, NameStr(*n), strlen(NameStr(*n)), regex_flavor, 0, NULL));}Datumtextregexeq(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_PP(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(RE_compile_and_execute(p, VARDATA_ANY(s), VARSIZE_ANY_EXHDR(s), regex_flavor, 0, NULL));}Datumtextregexne(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_PP(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, VARDATA_ANY(s), VARSIZE_ANY_EXHDR(s), 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_PP(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_PP(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_PP(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(RE_compile_and_execute(p, VARDATA_ANY(s), VARSIZE_ANY_EXHDR(s), regex_flavor | REG_ICASE, 0, NULL));}Datumtexticregexne(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_PP(0); text *p = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(!RE_compile_and_execute(p, VARDATA_ANY(s), VARSIZE_ANY_EXHDR(s), regex_flavor | REG_ICASE, 0, NULL));}/* * textregexsubstr() * Return a substring matched by a regular expression. */Datumtextregexsubstr(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_PP(0); text *p = PG_GETARG_TEXT_PP(1); regex_t *re; regmatch_t pmatch[2]; int so, eo; /* Compile RE */ re = RE_compile_and_cache(p, regex_flavor); /* * 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. */ if (!RE_execute(re, VARDATA_ANY(s), VARSIZE_ANY_EXHDR(s), 2, pmatch)) PG_RETURN_NULL(); /* definitely no match */ if (re->re_nsub > 0) { /* has parenthesized subexpressions, use the first one */ so = pmatch[1].rm_so; eo = pmatch[1].rm_eo; } else { /* no parenthesized subexpression, use whole match */ so = pmatch[0].rm_so; eo = pmatch[0].rm_eo; } /* * It is possible to have a match to the whole pattern but no match * for a subexpression; for example 'foo(bar)?' is considered to match * 'foo' but there is no subexpression match. So this extra test for * match failure is not redundant. */ if (so < 0 || eo < 0) PG_RETURN_NULL(); return DirectFunctionCall3(text_substr, PointerGetDatum(s), Int32GetDatum(so + 1), Int32GetDatum(eo - so));}/* * 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_PP(0); text *p = PG_GETARG_TEXT_PP(1); text *r = PG_GETARG_TEXT_PP(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_PP(0); text *p = PG_GETARG_TEXT_PP(1); text *r = PG_GETARG_TEXT_PP(2); text *opt = PG_GETARG_TEXT_PP(3); regex_t *re; pg_re_flags flags; parse_re_flags(&flags, opt); re = RE_compile_and_cache(p, flags.cflags); PG_RETURN_TEXT_P(replace_text_regexp(s, (void *) re, r, flags.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_PP(0); p = VARDATA_ANY(pat_text); plen = VARSIZE_ANY_EXHDR(pat_text); if (PG_ARGISNULL(1)) { /* No ESCAPE clause provided; default to backslash as escape */ e = "\\"; elen = 1; } else { esc_text = PG_GETARG_TEXT_PP(1); e = VARDATA_ANY(esc_text); elen = VARSIZE_ANY_EXHDR(esc_text); 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++ = '$'; SET_VARSIZE(result, r - ((char *) result)); PG_RETURN_TEXT_P(result);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?