summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/regexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/regexp.c')
-rw-r--r--src/backend/utils/adt/regexp.c350
1 files changed, 0 insertions, 350 deletions
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
deleted file mode 100644
index 69d00f18505..00000000000
--- a/src/backend/utils/adt/regexp.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * regexp.c
- * regular expression handling code.
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regexp.c,v 1.41 2002/06/20 20:29:38 momjian Exp $
- *
- * Alistair Crooks added the code for the regex caching
- * agc - cached the regular expressions used - there's a good chance
- * that we'll get a hit, so this saves a compile step for every
- * attempted match. I haven't actually measured the speed improvement,
- * but it `looks' a lot quicker visually when watching regression
- * test output.
- *
- * agc - incorporated Keith Bostic's Berkeley regex code into
- * the tree for all ports. To distinguish this regex code from any that
- * is existent on a platform, I've prepended the string "pg_" to
- * the functions regcomp, regerror, regexec and regfree.
- * Fixed a bug that was originally a typo by me, where `i' was used
- * instead of `oldest' when compiling regular expressions - benign
- * results mostly, although occasionally it bit you...
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "regex/regex.h"
-#include "utils/builtins.h"
-
-#if defined(DISABLE_XOPEN_NLS)
-#undef _XOPEN_SOURCE
-#endif /* DISABLE_XOPEN_NLS */
-
-/* this is the number of cached regular expressions held. */
-#ifndef MAX_CACHED_RES
-#define MAX_CACHED_RES 32
-#endif
-
-/* this structure describes a cached regular expression */
-struct cached_re_str
-{
- char *cre_s; /* pattern as null-terminated string */
- int cre_type; /* compiled-type: extended,icase etc */
- regex_t cre_re; /* the compiled regular expression */
- unsigned long cre_lru; /* lru tag */
-};
-
-static int rec = 0; /* # of cached re's */
-static struct cached_re_str rev[MAX_CACHED_RES]; /* cached re's */
-static unsigned long lru; /* system lru tag */
-static int pg_lastrec = 0;
-
-/* attempt to compile `re' as an re, then match it against text */
-/* cflags - flag to regcomp indicates case sensitivity */
-static bool
-RE_compile_and_execute(text *text_re, char *text, int cflags,
- int nmatch, regmatch_t *pmatch)
-{
- char *re;
- int oldest;
- int i;
- int regcomp_result;
-
- /* Convert 'text' pattern to null-terminated string */
- re = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(text_re)));
-
- /* Find a previously compiled regular expression.
- * Run the cache as a ring buffer, starting the search
- * from the previous match if any.
- */
- i = pg_lastrec;
- while (i < rec)
- {
- if (rev[i].cre_s != NULL)
- {
- if (strcmp(rev[i].cre_s, re) == 0 &&
- rev[i].cre_type == cflags)
- {
- pg_lastrec = i;
- rev[i].cre_lru = ++lru;
- pfree(re);
- return (pg_regexec(&rev[i].cre_re,
- text, nmatch,
- pmatch, 0) == 0);
- }
- }
- i++;
-
- /* If we were not at the first slot to start,
- * then think about wrapping if necessary.
- */
- if (pg_lastrec != 0)
- {
- if (i >= rec)
- {
- i = 0;
- }
- else if (i == pg_lastrec)
- {
- break;
- }
- }
- }
-
- /* we didn't find it - make room in the cache for it */
- if (rec >= MAX_CACHED_RES)
- {
- /* cache is full - find the oldest entry */
- for (oldest = 0, i = 1; i < rec; i++)
- {
- if (rev[i].cre_lru < rev[oldest].cre_lru)
- oldest = i;
- }
- }
- else
- {
- oldest = rec++;
- }
-
- /* if there was an old re, then de-allocate the space it used */
- if (rev[oldest].cre_s != (char *) NULL)
- {
- for (lru = i = 0; i < rec; i++)
- {
- /* downweight all of the other cached entries */
- rev[i].cre_lru = (rev[i].cre_lru - rev[oldest].cre_lru) / 2;
- if (rev[i].cre_lru > lru)
- lru = rev[i].cre_lru;
- }
- pg_regfree(&rev[oldest].cre_re);
-
- /*
- * use malloc/free for the cre_s field because the storage has to
- * persist across transactions
- */
- free(rev[oldest].cre_s);
- rev[oldest].cre_s = (char *) NULL;
- }
-
- /* compile the re */
- regcomp_result = pg_regcomp(&rev[oldest].cre_re, re, cflags);
- if (regcomp_result == 0)
- {
- pg_lastrec = oldest;
- /*
- * use malloc/free for the cre_s field because the storage has to
- * persist across transactions
- */
- rev[oldest].cre_s = strdup(re);
- rev[oldest].cre_lru = ++lru;
- rev[oldest].cre_type = cflags;
- pfree(re);
- /* agc - fixed an old typo here */
- return (pg_regexec(&rev[oldest].cre_re, text,
- nmatch, pmatch, 0) == 0);
- }
- else
- {
- char errMsg[1000];
-
- /* re didn't compile */
- pg_regerror(regcomp_result, &rev[oldest].cre_re, errMsg,
- sizeof(errMsg));
- elog(ERROR, "Invalid regular expression: %s", errMsg);
- }
-
- /* not reached */
- return false;
-}
-
-
-/*
- fixedlen_regexeq:
-
- a generic fixed length regexp routine
- s - the string to match against (not necessarily null-terminated)
- p - the pattern (as a text*)
- charlen - the length of the string
-*/
-static bool
-fixedlen_regexeq(char *s, text *p, int charlen, int cflags)
-{
- char *sterm;
- bool result;
-
- /* be sure sterm is null-terminated */
- sterm = (char *) palloc(charlen + 1);
- memcpy(sterm, s, charlen);
- sterm[charlen] = '\0';
-
- result = RE_compile_and_execute(p, sterm, cflags, 0, NULL);
-
- pfree(sterm);
-
- return result;
-}
-
-
-/*
- * interface routines called by the function manager
- */
-
-Datum
-nameregexeq(PG_FUNCTION_ARGS)
-{
- Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(fixedlen_regexeq(NameStr(*n),
- p,
- strlen(NameStr(*n)),
- REG_EXTENDED));
-}
-
-Datum
-nameregexne(PG_FUNCTION_ARGS)
-{
- Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(!fixedlen_regexeq(NameStr(*n),
- p,
- strlen(NameStr(*n)),
- REG_EXTENDED));
-}
-
-Datum
-textregexeq(PG_FUNCTION_ARGS)
-{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(fixedlen_regexeq(VARDATA(s),
- p,
- VARSIZE(s) - VARHDRSZ,
- REG_EXTENDED));
-}
-
-Datum
-textregexne(PG_FUNCTION_ARGS)
-{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(!fixedlen_regexeq(VARDATA(s),
- p,
- VARSIZE(s) - VARHDRSZ,
- REG_EXTENDED));
-}
-
-
-/*
- * routines that use the regexp stuff, but ignore the case.
- * for this, we use the REG_ICASE flag to pg_regcomp
- */
-
-
-Datum
-texticregexeq(PG_FUNCTION_ARGS)
-{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(fixedlen_regexeq(VARDATA(s),
- p,
- VARSIZE(s) - VARHDRSZ,
- REG_ICASE | REG_EXTENDED));
-}
-
-Datum
-texticregexne(PG_FUNCTION_ARGS)
-{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(!fixedlen_regexeq(VARDATA(s),
- p,
- VARSIZE(s) - VARHDRSZ,
- REG_ICASE | REG_EXTENDED));
-}
-
-Datum
-nameicregexeq(PG_FUNCTION_ARGS)
-{
- Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(fixedlen_regexeq(NameStr(*n),
- p,
- strlen(NameStr(*n)),
- REG_ICASE | REG_EXTENDED));
-}
-
-Datum
-nameicregexne(PG_FUNCTION_ARGS)
-{
- Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
-
- PG_RETURN_BOOL(!fixedlen_regexeq(NameStr(*n),
- p,
- strlen(NameStr(*n)),
- REG_ICASE | REG_EXTENDED));
-}
-
-
-/* textregexsubstr()
- * Return a substring matched by a regular expression.
- */
-Datum
-textregexsubstr(PG_FUNCTION_ARGS)
-{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
- char *sterm;
- int len;
- bool match;
- int nmatch = 1;
- regmatch_t pmatch;
-
- /* be sure sterm is null-terminated */
- len = VARSIZE(s) - VARHDRSZ;
- sterm = (char *) palloc(len + 1);
- memcpy(sterm, VARDATA(s), len);
- sterm[len] = '\0';
- /* We need the match info back from the pattern match
- * to be able to actually extract the substring.
- * It seems to be adequate to pass in a structure to return
- * only one result.
- */
- match = RE_compile_and_execute(p, sterm, REG_EXTENDED, nmatch, &pmatch);
- pfree(sterm);
-
- /* match? then return the substring matching the pattern */
- if (match)
- {
- return (DirectFunctionCall3(text_substr,
- PointerGetDatum(s),
- Int32GetDatum(pmatch.rm_so+1),
- Int32GetDatum(pmatch.rm_eo-pmatch.rm_so)));
- }
-
- PG_RETURN_NULL();
-}