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

Kenichi Sawada k @ sawada.cc
2007年 1月 12日 (金) 17:31:18 JST


はじめまして。澤田と申します。
pgpool、いつも大変便利に利用させて頂いております。ありがとうございます。

さて、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のようにして回避しても問題ないものでしょうか?

また、pgpool-3.1.2 にて同様の実験を実施したところ、今回の問題に関係なく
extended queryでない通常のDEALLOCATE文を実行した時点で常にエラーと
なるようです(ログ2:pgpool側ログをご参照ください)
これは恐らくpool_process_query.cの670行目からのif文:

  		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;

が、(pending_prepared_stmt->portal_nameがvolatileではないので)
恒真となってしまっているためと思われます。
この問題に加え、上記二重引用符の問題の回避を加えたpatchを
末尾Patch for 3.1.2として作成しましたが、こちらにつきましても
回避方法として適切かどうかにつきまして、皆様の御意見を頂ければ幸いです。
どうぞ宜しくお願い致します。

--澤田 研一
--k @ sawada.cc


----リスト1
#!/usr/bin/perl
use DBI;
my $dbh = DBI->connect("DBI:Pg:dbname=testdb;port=9999","postgres","");
my $sth = $dbh->prepare("select 1 = ?");
$sth->execute(1);
$sth->finish;
undef $sth;
$dbh->disconnect;
----リスト1ここまで


----ログ1
LOG:  statement: PREPARE dbdpg_1 AS select 1 = $1
LOG:  statement: <BIND> 
LOG:  statement: EXECUTE <unnamed>  [PREPARE:  select 1 = $1]
LOG:  statement: DEALLOCATE dbdpg_1
LOG:  statement:  RESET ALL
LOG:  statement:  SET SESSION AUTHORIZATION DEFAULT
LOG:  statement: DEALLOCATE "dbdpg_1"
ERROR:  prepared statement "dbdpg_1" does not exist
----ログ1ここまで


----ログ2
ERROR: pid 10245: SimpleForwardToBackend: strdup failed: Success
LOG:   pid 10245: do_child: exits with status 1 due to error
----ログ2ここまで


----Patch for 3.1.1
*** pool_process_query.c	2007-01-12 16:32:47.000000000 +0900
--- pool_process_query.c.org	2007-01-12 16:28:44.000000000 +0900
***************
*** 2519,2545 ****
  
  	if (kind == 'P' && *p)
  	{
! 		name_len = strlen(p) + 1;
  		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
! 		sprintf(name, "%s", p);
  		pending_function = add_prepared_list;
  		pending_prepared_name = name;
  	}
  	else if (kind == 'C' && *p == 'S' && *(p + 1))
  	{
! 		name_len = strlen(p + 1) + 1;
  		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
! 		sprintf(name, "%s", p + 1);
  		pending_function = del_prepared_list;
  		pending_prepared_name = name;
  	}
--- 2519,2545 ----
  
  	if (kind == 'P' && *p)
  	{
! 		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_function = add_prepared_list;
  		pending_prepared_name = name;
  	}
  	else if (kind == 'C' && *p == 'S' && *(p + 1))
  	{
! 		name_len = strlen(p + 1) + 3;
  		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
! 		sprintf(name, "\"%s\"", p + 1);
  		pending_function = del_prepared_list;
  		pending_prepared_name = name;
  	}
----Patch for 3.1.1ここまで


----Patch for 3.1.2
*** pool_process_query.c	2007-01-12 16:37:56.000000000 +0900
--- pool_process_query.c.org	2007-01-12 16:28:44.000000000 +0900
***************
*** 667,673 ****
  
  		pending_prepared_stmt->statement_name = strdup(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;
--- 667,674 ----
  
  		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;
***************
*** 2658,2671 ****
  	{
  		char *stmt;
  		
! 		name_len = strlen(p) + 1;
  		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,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)
***************
*** 2711,2724 ****
  			stmt = unnamed_statement;
  		else
  		{
! 			name = malloc(strlen(stmt_name) + 1);
  			if (name == NULL)
  			{
  				pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  				return POOL_END;
  			}
  
! 			sprintf(name, "%s", stmt_name);
  			stmt = lookup_prepared_statement_by_statement(&prepared_list, name);
  			free(name);
  		}
--- 2712,2725 ----
  			stmt = unnamed_statement;
  		else
  		{
! 			name = malloc(strlen(stmt_name) + 3);
  			if (name == NULL)
  			{
  				pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  				return POOL_END;
  			}
  
! 			sprintf(name, "\"%s\"", stmt_name);
  			stmt = lookup_prepared_statement_by_statement(&prepared_list, name);
  			free(name);
  		}
***************
*** 2737,2750 ****
  	}
  	else if (kind == 'C' && *p == 'S' && *(p + 1))
  	{
! 		name_len = strlen(p + 1) + 1;
  		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
! 		sprintf(name, "%s", p + 1);
  		pending_function = del_prepared_list;
  		pending_prepared_stmt = malloc(sizeof(PreparedStatement));
  		if (pending_prepared_stmt == NULL)
--- 2738,2751 ----
  	}
  	else if (kind == 'C' && *p == 'S' && *(p + 1))
  	{
! 		name_len = strlen(p + 1) + 3;
  		name = malloc(name_len);
  		if (name == NULL)
  		{
  			pool_error("SimpleForwardToBackend: malloc failed: %s", strerror(errno));
  			return POOL_END;
  		}
! 		sprintf(name, "\"%s\"", p + 1);
  		pending_function = del_prepared_list;
  		pending_prepared_stmt = malloc(sizeof(PreparedStatement));
  		if (pending_prepared_stmt == NULL)
----Patch for 3.1.2ここまで





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