diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-07-10 18:00:44 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-07-10 18:00:44 -0400 |
commit | a9287de1760450e7fe3b4309ee1ba7ea2af39217 (patch) | |
tree | 309455b0f7c242d78fda0048aad636765cd1e6b3 /src/backend/utils/adt/regexp.c | |
parent | ed45a5373029f2ff08ce76cf3807499afe3873ee (diff) | |
download | postgresql-a9287de1760450e7fe3b4309ee1ba7ea2af39217.tar.gz postgresql-a9287de1760450e7fe3b4309ee1ba7ea2af39217.zip |
Back-patch fix for extraction of fixed prefixes from regular expressions.
Back-patch of commits 628cbb50ba80c83917b07a7609ddec12cda172d0 and
c6aae3042be5249e672b731ebeb21875b5343010. This has been broken since
7.3, so back-patch to all supported branches.
Diffstat (limited to 'src/backend/utils/adt/regexp.c')
-rw-r--r-- | src/backend/utils/adt/regexp.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c index 0dbbd6715c9..c590f7e950e 100644 --- a/src/backend/utils/adt/regexp.c +++ b/src/backend/utils/adt/regexp.c @@ -1170,3 +1170,68 @@ build_regexp_split_result(regexp_matches_ctx *splitctx) Int32GetDatum(startpos + 1)); } } + +/* + * regexp_fixed_prefix - extract fixed prefix, if any, for a regexp + * + * The result is NULL if there is no fixed prefix, else a palloc'd string. + * If it is an exact match, not just a prefix, *exact is returned as TRUE. + */ +char * +regexp_fixed_prefix(text *text_re, bool case_insensitive, Oid collation, + bool *exact) +{ + char *result; + regex_t *re; + int cflags; + int re_result; + pg_wchar *str; + size_t slen; + size_t maxlen; + char errMsg[100]; + + *exact = false; /* default result */ + + /* Compile RE */ + cflags = REG_ADVANCED; + if (case_insensitive) + cflags |= REG_ICASE; + + re = RE_compile_and_cache(text_re, cflags, collation); + + /* Examine it to see if there's a fixed prefix */ + re_result = pg_regprefix(re, &str, &slen); + + switch (re_result) + { + case REG_NOMATCH: + return NULL; + + case REG_PREFIX: + /* continue with wchar conversion */ + break; + + case REG_EXACT: + *exact = true; + /* continue with wchar conversion */ + break; + + default: + /* re failed??? */ + pg_regerror(re_result, re, errMsg, sizeof(errMsg)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), + errmsg("regular expression failed: %s", errMsg))); + break; + } + + /* Convert pg_wchar result back to database encoding */ + maxlen = pg_database_encoding_max_length() * slen + 1; + result = (char *) palloc(maxlen); + slen = pg_wchar2mb_with_len(str, result, slen); + Assert(slen < maxlen); + + free(str); + + return result; +} |