regexp.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * regexp.c
  4.  *   regular expression handling code.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/regexp.c,v 1.22.2.1 1999/08/02 05:24:56 scrappy Exp $
  11.  *
  12.  * Alistair Crooks added the code for the regex caching
  13.  * agc - cached the regular expressions used - there's a good chance
  14.  * that we'll get a hit, so this saves a compile step for every
  15.  * attempted match. I haven't actually measured the speed improvement,
  16.  * but it `looks' a lot quicker visually when watching regression
  17.  * test output.
  18.  *
  19.  * agc - incorporated Keith Bostic's Berkeley regex code into
  20.  * the tree for all ports. To distinguish this regex code from any that
  21.  * is existent on a platform, I've prepended the string "pg95_" to
  22.  * the functions regcomp, regerror, regexec and regfree.
  23.  * Fixed a bug that was originally a typo by me, where `i' was used
  24.  * instead of `oldest' when compiling regular expressions - benign
  25.  * results mostly, although occasionally it bit you...
  26.  *
  27.  *
  28.  *-------------------------------------------------------------------------
  29.  */
  30. #include "postgres.h"
  31. #include "regex/regex.h"
  32. #include "utils/builtins.h"
  33. #if defined(DISABLE_XOPEN_NLS)
  34. #undef _XOPEN_SOURCE
  35. #endif  /* DISABLE_XOPEN_NLS */
  36. /* this is the number of cached regular expressions held. */
  37. #ifndef MAX_CACHED_RES
  38. #define MAX_CACHED_RES 32
  39. #endif
  40. /* this structure describes a cached regular expression */
  41. struct cached_re_str
  42. {
  43. struct varlena *cre_text; /* pattern as a text* */
  44. char    *cre_s; /* pattern as null-terminated string */
  45. int cre_type; /* compiled-type: extended,icase etc */
  46. regex_t cre_re; /* the compiled regular expression */
  47. unsigned long cre_lru; /* lru tag */
  48. };
  49. static int rec = 0; /* # of cached re's */
  50. static struct cached_re_str rev[MAX_CACHED_RES]; /* cached re's */
  51. static unsigned long lru; /* system lru tag */
  52. /* attempt to compile `re' as an re, then match it against text */
  53. /* cflags - flag to regcomp indicates case sensitivity */
  54. static int
  55. RE_compile_and_execute(struct varlena * text_re, char *text, int cflags)
  56. {
  57. int oldest;
  58. int n;
  59. int i;
  60. char    *re;
  61. int regcomp_result;
  62. re = textout(text_re);
  63. /* find a previously compiled regular expression */
  64. for (i = 0; i < rec; i++)
  65. {
  66. if (rev[i].cre_s)
  67. {
  68. if (strcmp(rev[i].cre_s, re) == 0)
  69. {
  70. if (rev[i].cre_type == cflags)
  71. {
  72. rev[i].cre_lru = ++lru;
  73. pfree(re);
  74. return (pg95_regexec(&rev[i].cre_re,
  75.  text, 0,
  76.  (regmatch_t *) NULL, 0) == 0);
  77. }
  78. }
  79. }
  80. }
  81. /* we didn't find it - make room in the cache for it */
  82. if (rec == MAX_CACHED_RES)
  83. {
  84. /* cache is full - find the oldest entry */
  85. for (oldest = 0, i = 1; i < rec; i++)
  86. {
  87. if (rev[i].cre_lru < rev[oldest].cre_lru)
  88. oldest = i;
  89. }
  90. }
  91. else
  92. oldest = rec++;
  93. /* if there was an old re, then de-allocate the space it used */
  94. if (rev[oldest].cre_s != (char *) NULL)
  95. {
  96. for (lru = i = 0; i < rec; i++)
  97. {
  98. rev[i].cre_lru = (rev[i].cre_lru - rev[oldest].cre_lru) / 2;
  99. if (rev[i].cre_lru > lru)
  100. lru = rev[i].cre_lru;
  101. }
  102. pg95_regfree(&rev[oldest].cre_re);
  103. /*
  104.  * use malloc/free for the cre_s field because the storage has to
  105.  * persist across transactions
  106.  */
  107. free(rev[oldest].cre_s);
  108. }
  109. /* compile the re */
  110. regcomp_result = pg95_regcomp(&rev[oldest].cre_re, re, cflags);
  111. if (regcomp_result == 0)
  112. {
  113. n = strlen(re);
  114. /*
  115.  * use malloc/free for the cre_s field because the storage has to
  116.  * persist across transactions
  117.  */
  118. rev[oldest].cre_s = (char *) malloc(n + 1);
  119. memmove(rev[oldest].cre_s, re, n);
  120. rev[oldest].cre_s[n] = 0;
  121. rev[oldest].cre_text = text_re;
  122. rev[oldest].cre_lru = ++lru;
  123. rev[oldest].cre_type = cflags;
  124. pfree(re);
  125. /* agc - fixed an old typo here */
  126. return (pg95_regexec(&rev[oldest].cre_re, text, 0,
  127.  (regmatch_t *) NULL, 0) == 0);
  128. }
  129. else
  130. {
  131. char errMsg[1000];
  132. /* re didn't compile */
  133. rev[oldest].cre_s = (char *) NULL;
  134. pg95_regerror(regcomp_result, &rev[oldest].cre_re, errMsg,
  135.   sizeof(errMsg));
  136. elog(ERROR, "regcomp failed with error %s", errMsg);
  137. }
  138. /* not reached */
  139. return 0;
  140. }
  141. /*
  142.  * interface routines called by the function manager
  143.  */
  144. /*
  145.    fixedlen_regexeq:
  146.    a generic fixed length regexp routine
  147.  s - the string to match against (not necessarily null-terminated)
  148.  p - the pattern
  149.  charlen   - the length of the string
  150. */
  151. static bool
  152. fixedlen_regexeq(char *s, struct varlena * p, int charlen, int cflags)
  153. {
  154. char    *sterm;
  155. int result;
  156. if (!s || !p)
  157. return FALSE;
  158. /* be sure sterm is null-terminated */
  159. sterm = (char *) palloc(charlen + 1);
  160. StrNCpy(sterm, s, charlen + 1);
  161. result = RE_compile_and_execute(p, sterm, cflags);
  162. pfree(sterm);
  163. return (bool) result;
  164. }
  165. /*
  166.  * routines that use the regexp stuff
  167.  */
  168. bool
  169. nameregexeq(NameData *n, struct varlena * p)
  170. {
  171. if (!n)
  172. return FALSE;
  173. return fixedlen_regexeq(n->data, p, NAMEDATALEN, REG_EXTENDED);
  174. }
  175. bool
  176. nameregexne(NameData *s, struct varlena * p)
  177. {
  178. return !nameregexeq(s, p);
  179. }
  180. bool
  181. textregexeq(struct varlena * s, struct varlena * p)
  182. {
  183. if (!s)
  184. return FALSE;
  185. return fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ, REG_EXTENDED);
  186. }
  187. bool
  188. textregexne(struct varlena * s, struct varlena * p)
  189. {
  190. return !textregexeq(s, p);
  191. }
  192. /*
  193. *  routines that use the regexp stuff, but ignore the case.
  194.  * for this, we use the REG_ICASE flag to pg95_regcomp
  195.  */
  196. bool
  197. texticregexeq(struct varlena * s, struct varlena * p)
  198. {
  199. if (!s)
  200. return FALSE;
  201. return (fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ,
  202.  REG_ICASE | REG_EXTENDED));
  203. }
  204. bool
  205. texticregexne(struct varlena * s, struct varlena * p)
  206. {
  207. return !texticregexeq(s, p);
  208. }
  209. bool
  210. nameicregexeq(NameData *n, struct varlena * p)
  211. {
  212. if (!n)
  213. return FALSE;
  214. return (fixedlen_regexeq(n->data, p, NAMEDATALEN,
  215.  REG_ICASE | REG_EXTENDED));
  216. }
  217. bool
  218. nameicregexne(NameData *s, struct varlena * p)
  219. {
  220. return !nameicregexeq(s, p);
  221. }