-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Le 21/12/2010 15:11, Gilles Darold a écrit :
> [...]
> Regex patch :
> 
>     The regex struct array is stored in pool_config struct, it is
>     dynamically expendable by PATTERN_ARR_SIZE when it reached
>     NxPATTERN_ARR_SIZE (start with 16 regex max).
> 
>     All entries in white_function_list or black_function_list are stored
>     in this array with a flag to differentiate them. To preserve
>     backward compatibility and prevent partial matching lists entries
>     are all prefixed with '^' and ended with '$' if not already done.
>     This also mean that if we want to match function beginning with
>     "write_" it has to be written : "write_.*". Indeed "^write_.*$"
>     works too.
> 

Not much to say. It applies, it compiles, and it works. I didn't try
really big regexp, but I'm quite sure it doesn't aim for big regexps.

See attached patch.

Thanks Gilles.


- -- 
Guillaume Lelarge
Administrateur de bases de données
http://dalibo.com - http://dalibo.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk0Uy8YACgkQeWXglSY0snlM3wCguu4b6i2J5p6+00BqziTxypcl
3OYAn04ewYSIwD6GuNX8ezRNzRmgT9VX
=hQoP
-----END PGP SIGNATURE-----
Index: pool_config.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.c,v
retrieving revision 1.52
diff -c -p -r1.52 pool_config.c
*** pool_config.c	17 Aug 2010 02:09:00 -0000	1.52
--- pool_config.c	24 Dec 2010 15:59:17 -0000
*************** int pool_init_config(void)
*** 1926,1931 ****
--- 1926,1934 ----
  	pool_config->ssl_ca_cert = "";
  	pool_config->ssl_ca_cert_dir = "";
  	pool_config->debug_level = 0;
+     pool_config->lists_patterns = NULL;
+     pool_config->pattc = 0;
+     pool_config->current_pattern_size = 0;
  
  	res = gethostname(localhostname,sizeof(localhostname));
  	if(res !=0 )
*************** int pool_init_config(void)
*** 1941,1946 ****
--- 1944,2041 ----
  	return 0;
  }
  
+ /* 
+  * Add regex expression to patterns array
+  * The supported type are: black_function_list and white_function_list
+  * Return 0 on error, 1 on success
+  */
+ int add_regex_pattern(char *type, char *s)
+ {
+ 	int regex_flags = REG_NOSUB;
+ 	RegPattern currItem;
+ 	/* force case insensitive pattern matching */
+ 	regex_flags |= REG_ICASE;
+ 	/* Add extended regex search */
+ 	regex_flags |= REG_EXTENDED;
+ 	/* Fill the pattern type */
+ 	if (strcmp(type, "black_function_list") == 0)
+ 	{
+ 		currItem.type = BLACKLIST;
+ 	}
+ 	else if (strcmp(type, "white_function_list") == 0)
+ 	{
+ 		currItem.type = WHITELIST;
+ 	}
+ 	else
+ 	{
+ 		pool_error("add_to_patterns: bad pattern type %s", type);
+ 		return 0;
+ 	}
+ 	/* Fill the pattern flag */
+ 	currItem.flag = regex_flags;
+ 
+ 	/* Fill pattern array */
+ 	currItem.pattern = malloc(sizeof(char)*(strlen(s)+1));
+ 	if (currItem.pattern == NULL)
+ 	{
+ 		pool_error("add_to_patterns: unable to allocate new pattern");
+ 		return 0;
+ 	}
+ 	/* Force exact matching of function name with ^ and $ on the regex
+ 	   if required to prevent partial matching. It also allow backward
+ 	   compatibility.
+ 	 */
+ 	if (strncmp(s, "^", 1) != 0) {
+ 		strncpy(currItem.pattern, "^", 2);
+ 		strncat(currItem.pattern, s, strlen(s) + 1);
+ 	} else {
+ 		strncpy(currItem.pattern, s, strlen(s) + 1);
+ 	}
+ 	if (s[strlen(s)-1] != '$') {
+ 		strncat(currItem.pattern, "$", 2);
+ 	}
+ 	pool_debug("add_to_patterns: regex pattern: %s", currItem.pattern);
+ 	/* compile our regex */
+ 	if (regcomp(&currItem.regexv, currItem.pattern, currItem.flag) != 0)
+ 	{
+ 		pool_error("add_to_patterns: invalid regex pattern: %s", currItem.pattern);
+ 	}
+ 	else
+ 	{
+ 		if (growPatternArray(currItem) < 0)
+ 		{
+ 			pool_error("add_to_patterns: unable to allocate new pattern");
+ 			return 0;
+ 		}
+ 	}
+ 	return 1;
+ }
+ 
+ /* 
+  * Dynamically grow the regex pattern array
+  * The array start with PATTERN_ARR_SIZE storage place, if required
+  * it will grow of PATTERN_ARR_SIZE more each time.
+  */
+ int growPatternArray (RegPattern item)
+ {
+ 	void *_tmp = NULL;
+ 	if (pool_config->pattc == pool_config->current_pattern_size)
+ 	{
+ 		pool_config->current_pattern_size += PATTERN_ARR_SIZE;
+ 		_tmp = realloc(pool_config->lists_patterns, (pool_config->current_pattern_size * sizeof(RegPattern)));
+ 		if (!_tmp)
+ 		{
+ 			return(-1);
+ 		}
+ 
+ 		pool_config->lists_patterns = (RegPattern*)_tmp;
+ 	}
+ 	pool_config->lists_patterns[pool_config->pattc] = item;
+ 	pool_config->pattc++;
+ 
+ 	return(pool_config->pattc);
+ }
+ 
  int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
  {
  	FILE *fd;
Index: pool_config.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.h,v
retrieving revision 1.8
diff -c -p -r1.8 pool_config.h
*** pool_config.h	1 Aug 2010 08:38:17 -0000	1.8
--- pool_config.h	24 Dec 2010 15:59:17 -0000
***************
*** 33,38 ****
--- 33,53 ----
  #define MODE_SLONY "slony"		/* Slony-I */
  
  /*
+  *  Regex support in white and black list function
+  */
+ #include <regex.h>
+ #define BLACKLIST	0
+ #define WHITELIST	1
+ #define PATTERN_ARR_SIZE 16     /* Default length of regex array: 16 patterns */
+ typedef struct {
+   char *pattern;
+   int type;
+   int flag;
+   regex_t regexv;
+ } RegPattern;
+ 
+ 
+ /*
   * configuration paramters
   */
  typedef struct {
*************** typedef struct {
*** 149,154 ****
--- 164,174 ----
  	char *ssl_key;	/* path to ssl key (frontend only) */
  	char *ssl_ca_cert;	/* path to root (CA) certificate */
  	char *ssl_ca_cert_dir;	/* path to directory containing CA certificates */
+ 
+ 	/* followings are for regex support and do not exist in the configuration file */
+ 	RegPattern *lists_patterns; /* Precompiled regex patterns for black/white lists */
+ 	int pattc; /* number of regexp pattern */
+ 	int current_pattern_size; /* size of the regex pattern array */
  } POOL_CONFIG;
  
  typedef enum {
*************** extern int pool_init_config(void);
*** 162,165 ****
--- 182,190 ----
  extern int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context);
  extern int eval_logical(char *str);
  
+ /* methods used for regexp support */
+ extern int add_regex_pattern(char *type, char *s);
+ extern int growPatternArray (RegPattern item);
+ extern int pattern_compare(char *str, const int type);
+ 
  #endif /* POOL_CONFIG_H */
Index: pool_config.l
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.l,v
retrieving revision 1.48
diff -c -p -r1.48 pool_config.l
*** pool_config.l	17 Aug 2010 02:09:00 -0000	1.48
--- pool_config.l	24 Dec 2010 15:59:18 -0000
*************** int pool_init_config(void)
*** 201,206 ****
--- 203,211 ----
  	pool_config->ssl_ca_cert = "";
  	pool_config->ssl_ca_cert_dir = "";
  	pool_config->debug_level = 0;
+ 	pool_config->lists_patterns = NULL;
+ 	pool_config->pattc = 0;
+ 	pool_config->current_pattern_size = 0;
  
  	res = gethostname(localhostname,sizeof(localhostname));
  	if(res !=0 )
*************** int pool_init_config(void)
*** 216,221 ****
--- 221,318 ----
  	return 0;
  }
  
+ /* 
+  * Add regex expression to patterns array
+  * The supported type are: black_function_list and white_function_list
+  * Return 0 on error, 1 on success
+  */
+ int add_regex_pattern(char *type, char *s)
+ {
+ 	int regex_flags = REG_NOSUB;
+ 	RegPattern currItem;
+ 	/* force case insensitive pattern matching */
+ 	regex_flags |= REG_ICASE;
+ 	/* Add extended regex search */
+ 	regex_flags |= REG_EXTENDED;
+ 	/* Fill the pattern type */
+ 	if (strcmp(type, "black_function_list") == 0)
+ 	{
+ 		currItem.type = BLACKLIST;
+ 	}
+ 	else if (strcmp(type, "white_function_list") == 0)
+ 	{
+ 		currItem.type = WHITELIST;
+ 	}
+ 	else
+ 	{
+ 		pool_error("add_to_patterns: bad pattern type %s", type);
+ 		return 0;
+ 	}
+ 	/* Fill the pattern flag */
+ 	currItem.flag = regex_flags;
+ 
+ 	/* Fill pattern array */
+ 	currItem.pattern = malloc(sizeof(char)*(strlen(s)+1));
+ 	if (currItem.pattern == NULL)
+ 	{
+ 		pool_error("add_to_patterns: unable to allocate new pattern");
+ 		return 0;
+ 	}
+ 	/* Force exact matching of function name with ^ and $ on the regex
+ 	   if required to prevent partial matching. It also allow backward
+ 	   compatibility.
+ 	 */
+ 	if (strncmp(s, "^", 1) != 0) {
+ 		strncpy(currItem.pattern, "^", 2);
+ 		strncat(currItem.pattern, s, strlen(s) + 1);
+ 	} else {
+ 		strncpy(currItem.pattern, s, strlen(s) + 1);
+ 	}
+ 	if (s[strlen(s)-1] != '$') {
+ 		strncat(currItem.pattern, "$", 2);
+ 	}
+ 	pool_debug("add_to_patterns: regex pattern: %s", currItem.pattern);
+ 	/* compile our regex */
+ 	if (regcomp(&currItem.regexv, currItem.pattern, currItem.flag) != 0)
+ 	{
+ 		pool_error("add_to_patterns: invalid regex pattern: %s", currItem.pattern);
+ 	}
+ 	else
+ 	{
+ 		if (growPatternArray(currItem) < 0)
+ 		{
+ 			pool_error("add_to_patterns: unable to allocate new pattern");
+ 			return 0;
+ 		}
+ 	}
+ 	return 1;
+ }
+ 
+ /* 
+  * Dynamically grow the regex pattern array
+  * The array start with PATTERN_ARR_SIZE storage place, if required
+  * it will grow of PATTERN_ARR_SIZE more each time.
+  */
+ int growPatternArray (RegPattern item)
+ {
+ 	void *_tmp = NULL;
+ 	if (pool_config->pattc == pool_config->current_pattern_size)
+ 	{
+ 		pool_config->current_pattern_size += PATTERN_ARR_SIZE;
+ 		_tmp = realloc(pool_config->lists_patterns, (pool_config->current_pattern_size * sizeof(RegPattern)));
+ 		if (!_tmp)
+ 		{
+ 			return(-1);
+ 		}
+ 
+ 		pool_config->lists_patterns = (RegPattern*)_tmp;
+ 	}
+ 	pool_config->lists_patterns[pool_config->pattc] = item;
+ 	pool_config->pattc++;
+ 
+ 	return(pool_config->pattc);
+ }
+ 
  int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
  {
  	FILE *fd;
*************** int pool_get_config(char *confpath, POOL
*** 701,706 ****
--- 798,807 ----
  				fclose(fd);
  				return(-1);
  			}
+ 			for (i=0;i<pool_config->num_white_function_list;i++)
+ 			{
+ 				add_regex_pattern("white_function_list", pool_config->white_function_list[i]);
+ 			}
  		}
  
  		else if (!strcmp(key, "black_function_list") &&
*************** int pool_get_config(char *confpath, POOL
*** 728,733 ****
--- 829,838 ----
  				fclose(fd);
  				return(-1);
  			}
+ 			for (i=0;i<pool_config->num_black_function_list;i++)
+ 			{
+ 				add_regex_pattern("black_function_list", pool_config->black_function_list[i]);
+ 			}
  		}
  
  		else if (!strcmp(key, "print_timestamp") && CHECK_CONTEXT(INIT_CONFIG, context))
Index: pool_select_walker.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_select_walker.c,v
retrieving revision 1.6
diff -c -p -r1.6 pool_select_walker.c
*** pool_select_walker.c	6 Sep 2010 05:03:21 -0000	1.6
--- pool_select_walker.c	24 Dec 2010 15:59:18 -0000
*************** bool pool_has_temp_table(Node *node)
*** 97,108 ****
  }
  
  /*
   * Walker function to find a function call
   */
  static bool function_call_walker(Node *node, void *context)
  {
  	SelectContext	*ctx = (SelectContext *) context;
- 	int i;
  
  	if (node == NULL)
  		return false;
--- 97,143 ----
  }
  
  /*
+  * Search function name in whilelist or blacklist regex array
+  * Return 1 on success (found in list)
+  * Return 0 when not found in list
+  * Return -1 if the given search type doesn't exist.
+  * Search type supported are: WHITELIST and BLACKLIST 
+  */
+ int pattern_compare(char *str, const int type)
+ {
+ 	int i = 0;
+ 
+ 	/* pass througth all regex pattern unless pattern is found */
+ 	for (i = 0; i < pool_config->pattc; i++) {
+ 		if ( (pool_config->lists_patterns[i].type == type) && (regexec(&pool_config->lists_patterns[i].regexv, str, 0, 0, 0) == 0) ) {
+ 			switch(type) {
+ 			/* return 1 if string matches whitelist pattern */
+ 			case WHITELIST:
+ 				if (pool_config->debug_level > 0)
+ 					pool_debug("pattern_compare: white_function_list (%s) matched: %s", pool_config->lists_patterns[i].pattern, str);
+ 				return 1;
+ 			/* return 1 if string matches blacklist pattern */
+ 			case BLACKLIST:
+ 				if (pool_config->debug_level > 0)
+ 					pool_debug("pattern_compare: black_function_list (%s) matched: %s", pool_config->lists_patterns[i].pattern, str);
+ 				return 1;
+ 			default:
+ 				pool_error("pattern_compare: unknown pattern match type: %s", str);
+ 				return -1;
+ 			}
+ 		}
+ 	}
+ 
+ 	/* return 0 otherwise */
+ 	return 0;
+ }
+ 
+ /*
   * Walker function to find a function call
   */
  static bool function_call_walker(Node *node, void *context)
  {
  	SelectContext	*ctx = (SelectContext *) context;
  
  	if (node == NULL)
  		return false;
*************** static bool function_call_walker(Node *n
*** 123,135 ****
  			 */
  			if (pool_config->num_white_function_list > 0)
  			{
! 				for (i=0;i<pool_config->num_white_function_list;i++)
! 				{
  					/* If the function is found in the white list, we can ignore it */
! 					if (!strcasecmp(pool_config->white_function_list[i], fname))
! 					{
! 						return raw_expression_tree_walker(node, function_call_walker, context);
! 					}
  				}
  				/*
  				 * Since the function was not found in white list, we
--- 158,167 ----
  			 */
  			if (pool_config->num_white_function_list > 0)
  			{
! 				/* Search function in the white list regex patterns */
! 				if (pattern_compare(fname, WHITELIST) == 1) {
  					/* If the function is found in the white list, we can ignore it */
! 					return raw_expression_tree_walker(node, function_call_walker, context);
  				}
  				/*
  				 * Since the function was not found in white list, we
*************** static bool function_call_walker(Node *n
*** 142,152 ****
  			/*
  			 * Check black list if any.
  			 */
! 			for (i=0;i<pool_config->num_black_function_list;i++)
  			{
! 				/* Is the function found in the black list? */
! 				if (!strcasecmp(pool_config->black_function_list[i], fname))
! 				{
  					/* Found. */
  					ctx->has_function_call = true;
  					return false;
--- 174,183 ----
  			/*
  			 * Check black list if any.
  			 */
! 			if (pool_config->num_black_function_list > 0)
  			{
! 				/* Search function in the black list regex patterns */
! 				if (pattern_compare(fname, BLACKLIST) == 1) {
  					/* Found. */
  					ctx->has_function_call = true;
  					return false;

Attachment: regexp.patch.sig
Description: Binary data

_______________________________________________
Pgpool-hackers mailing list
[email protected]
http://pgfoundry.org/mailman/listinfo/pgpool-hackers

Reply via email to