[pgpool-general-jp: 74] Re: pgpoolのprepared_listについて

Yoshiyuki Asaba y-asaba @ sraoss.co.jp
2007年 1月 12日 (金) 19:29:41 JST


浅羽です。

From: Kenichi Sawada <k @ sawada.cc>
Subject: [pgpool-general-jp: 71] pgpoolのprepared_listについて
Date: Fri, 12 Jan 2007 17:31:18 +0900 (JST)

> さて、PostgreSQL-8.1.4, Perl-5.8.5, DBI-1.51, DBD-Pg-1.49 という環境にて、
> pgpool-3.1.1 をport 9999上で動作させている状況で、
> create testdbとしてtestdbを作成してリスト1のスクリプトを実行させると、
> PostgreSQL側に
> ERROR:  prepared statement "dbdpg_1" does not exist
> というエラーログが出るようです(ログ1:PostgreSQL側ログをご参照ください)
> 
> これはpool_process_query.cの中でextended queryのstatement_nameについて
> 常に二重引用符を付加しているために発生する現象ではないかと思いますが、
> これは末尾Patch for 3.1.1のようにして回避しても問題ないものでしょう
> か?

パッチありがとうございます。JDBC ドライバを使ったテストしかしていなかっ
たため、開発中には気付きませんでした…。

パッチですが、

  prepare a as select 1;

という prepared statement があった場合に、

  deallocate a;
  deallocate "a";
  deallocate A;

というクエリに対応しないといけないため、少し手を加えてみました。こちら
でいかがでしょうか?

--
Yoshiyuki Asaba
y-asaba @ sraoss.co.jp
-------------- next part --------------
Index: pool_process_query.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool/pool_process_query.c,v
retrieving revision 1.35
diff -c -r1.35 pool_process_query.c
*** pool_process_query.c	4 Jan 2007 17:01:36 -0000	1.35
--- pool_process_query.c	11 Jan 2007 05:35:52 -0000
***************
*** 133,138 ****
--- 133,139 ----
  static PreparedStatement *lookup_prepared_statement_by_statement(PreparedStatementList *p, const char *name);
  static PreparedStatement *lookup_prepared_statement_by_portal(PreparedStatementList *p, const char *name);
  static int send_deallocate(POOL_CONNECTION_POOL *backend, PreparedStatementList *p, int n);
+ static char *normalize_prepared_stmt_name(const char *name);
  
  static POOL_CONNECTION_POOL_SLOT *slots[MAX_CONNECTION_SLOTS];
  
***************
*** 665,674 ****
  			return POOL_END;
  		}
  
! 		pending_prepared_stmt->statement_name = strdup(name);
  		pending_prepared_stmt->portal_name = NULL;
! 		if (pending_prepared_stmt->portal_name == NULL ||
! 			pending_prepared_stmt->statement_name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: strdup failed: %s", strerror(errno));
  			return POOL_END;
--- 666,674 ----
  			return POOL_END;
  		}
  
! 		pending_prepared_stmt->statement_name = normalize_prepared_stmt_name(name);
  		pending_prepared_stmt->portal_name = NULL;
! 		if (pending_prepared_stmt->statement_name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: strdup failed: %s", strerror(errno));
  			return POOL_END;
***************
*** 2659,2672 ****
  	{
  		char *stmt;
  		
! 		name_len = strlen(p) + 3;
! 		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
- 		sprintf(name, "\"%s\"", p);
  
  		pending_prepared_stmt = malloc(sizeof(PreparedStatement));
  		if (pending_prepared_stmt == NULL)
--- 2659,2670 ----
  	{
  		char *stmt;
  		
! 		name = strdup(p);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
  
  		pending_prepared_stmt = malloc(sizeof(PreparedStatement));
  		if (pending_prepared_stmt == NULL)
***************
*** 2732,2738 ****
  		{
  			if (stmt->portal_name)
  				free(stmt->portal_name);
! 			stmt->portal_name = strdup(portal_name);
  		}
  
  	}
--- 2730,2736 ----
  		{
  			if (stmt->portal_name)
  				free(stmt->portal_name);
! 			stmt->portal_name = strdup(stmt->portal_name);
  		}
  
  	}
***************
*** 2754,2760 ****
  			return POOL_END;
  		}
  
! 		pending_prepared_stmt->statement_name = strdup(name);
  		if (pending_prepared_stmt->statement_name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
--- 2752,2758 ----
  			return POOL_END;
  		}
  
! 		pending_prepared_stmt->statement_name = normalize_prepared_stmt_name(name);
  		if (pending_prepared_stmt->statement_name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
***************
*** 3431,3442 ****
  	memcpy(string, query, len);
  
  	stmt = malloc(sizeof(PreparedStatement));
! 	stmt->statement_name = strdup(portal);
  	stmt->portal_name = NULL;
  	stmt->prepared_string = string;
  
- 	pool_debug("get_prepared_command_portal_and_statement: extracted portal name: %s  portal statement: %s", stmt->portal_name, stmt->prepared_string);
- 
  	return stmt;
  }
  
--- 3429,3438 ----
  	memcpy(string, query, len);
  
  	stmt = malloc(sizeof(PreparedStatement));
! 	stmt->statement_name = normalize_prepared_stmt_name(portal);
  	stmt->portal_name = NULL;
  	stmt->prepared_string = string;
  
  	return stmt;
  }
  
***************
*** 3618,3631 ****
  	if (p->cnt <= n)
  		return 1;
  	
! 	len = strlen(p->stmt_list[n]->statement_name) + 12; /* "DEALLOCATE " + '\0' */
  	query = malloc(len);
  	if (query == NULL)
  	{
  		pool_error("send_deallocate: malloc failed: %s", strerror(errno));
  		exit(1);
  	}
! 	sprintf(query, "DEALLOCATE %s", p->stmt_list[n]->statement_name);
  	if (Query(NULL, backend, query) != POOL_CONTINUE)
  	{
  		free(query);
--- 3614,3627 ----
  	if (p->cnt <= n)
  		return 1;
  	
! 	len = strlen(p->stmt_list[n]->statement_name) + 14; /* "DEALLOCATE \"" + "\"" + '\0' */
  	query = malloc(len);
  	if (query == NULL)
  	{
  		pool_error("send_deallocate: malloc failed: %s", strerror(errno));
  		exit(1);
  	}
! 	sprintf(query, "DEALLOCATE \"%s\"", p->stmt_list[n]->statement_name);
  	if (Query(NULL, backend, query) != POOL_CONTINUE)
  	{
  		free(query);
***************
*** 3635,3637 ****
--- 3631,3666 ----
  
  	return 0;
  }
+ 
+ static char *normalize_prepared_stmt_name(const char *name)
+ {
+ 	char *result;
+ 	int i, len;
+ 
+ 	len = strlen(name);
+ 
+ 	if (name[0] != '"' && name[len-1] != '"')
+ 	{
+ 		result = strdup(name);
+ 		if (result == NULL)
+ 			return result;
+ 		for (i = 0; i < len; i++)
+ 		{
+ 			if (isupper(result[i]))
+ 			{
+ 				result[i] += 32; /* convert to lower */
+ 			}
+ 		}
+ 	}
+ 	else
+ 	{
+ 		result = malloc(len - 1);
+ 		if (result == NULL)
+ 			return result;
+ 
+ 		result = memcpy(result, name+1, len-2);
+ 		result[len-1] = '\0';
+ 	}
+ 
+ 	return result;
+ }


pgpool-general-jp メーリングリストの案内