aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/regexp.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-07-10 18:00:44 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-07-10 18:00:44 -0400
commita9287de1760450e7fe3b4309ee1ba7ea2af39217 (patch)
tree309455b0f7c242d78fda0048aad636765cd1e6b3 /src/backend/utils/adt/regexp.c
parented45a5373029f2ff08ce76cf3807499afe3873ee (diff)
downloadpostgresql-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.c65
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;
+}