mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix core dump in duration logging for a V3-protocol Execute message
when what's being executed is a COMMIT or ROLLBACK. Per report from Sergey Koposov. Backpatch to 8.1; 8.0 and before don't have the bug due to lack of any logging at all here.
This commit is contained in:
		@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.468.2.5 2006/06/11 15:49:36 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.468.2.6 2006/08/13 22:18:22 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *	  this is the "main" module of the postgres backend and
 | 
					 *	  this is the "main" module of the postgres backend and
 | 
				
			||||||
@@ -1642,12 +1642,14 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
	Portal		portal;
 | 
						Portal		portal;
 | 
				
			||||||
	bool		completed;
 | 
						bool		completed;
 | 
				
			||||||
	char		completionTag[COMPLETION_TAG_BUFSIZE];
 | 
						char		completionTag[COMPLETION_TAG_BUFSIZE];
 | 
				
			||||||
 | 
						const char *sourceText = NULL;
 | 
				
			||||||
	struct timeval start_t,
 | 
						struct timeval start_t,
 | 
				
			||||||
				stop_t;
 | 
									stop_t;
 | 
				
			||||||
	bool		save_log_duration = log_duration;
 | 
						bool		save_log_duration = log_duration;
 | 
				
			||||||
	int			save_log_min_duration_statement = log_min_duration_statement;
 | 
						int			save_log_min_duration_statement = log_min_duration_statement;
 | 
				
			||||||
	bool		save_log_statement_stats = log_statement_stats;
 | 
						bool		save_log_statement_stats = log_statement_stats;
 | 
				
			||||||
	bool		execute_is_fetch = false;
 | 
						bool		is_xact_command;
 | 
				
			||||||
 | 
						bool		execute_is_fetch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Adjust destination to tell printtup.c what to do */
 | 
						/* Adjust destination to tell printtup.c what to do */
 | 
				
			||||||
	dest = whereToSendOutput;
 | 
						dest = whereToSendOutput;
 | 
				
			||||||
@@ -1660,15 +1662,6 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
				(errcode(ERRCODE_UNDEFINED_CURSOR),
 | 
									(errcode(ERRCODE_UNDEFINED_CURSOR),
 | 
				
			||||||
				 errmsg("portal \"%s\" does not exist", portal_name)));
 | 
									 errmsg("portal \"%s\" does not exist", portal_name)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * If we re-issue an Execute protocol request against an existing portal,
 | 
					 | 
				
			||||||
	 * then we are only fetching more rows rather than completely re-executing
 | 
					 | 
				
			||||||
	 * the query from the start. atStart is never reset for a v3 portal, so we
 | 
					 | 
				
			||||||
	 * are safe to use this check.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (!portal->atStart)
 | 
					 | 
				
			||||||
		execute_is_fetch = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If the original query was a null string, just return
 | 
						 * If the original query was a null string, just return
 | 
				
			||||||
	 * EmptyQueryResponse.
 | 
						 * EmptyQueryResponse.
 | 
				
			||||||
@@ -1680,6 +1673,17 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Does the portal contain a transaction command? */
 | 
				
			||||||
 | 
						is_xact_command = IsTransactionStmtList(portal->parseTrees);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If we re-issue an Execute protocol request against an existing portal,
 | 
				
			||||||
 | 
						 * then we are only fetching more rows rather than completely re-executing
 | 
				
			||||||
 | 
						 * the query from the start. atStart is never reset for a v3 portal, so we
 | 
				
			||||||
 | 
						 * are safe to use this check.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						execute_is_fetch = !portal->atStart;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Should we display the portal names here? */
 | 
						/* Should we display the portal names here? */
 | 
				
			||||||
	if (execute_is_fetch)
 | 
						if (execute_is_fetch)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1688,8 +1692,18 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	else if (portal->sourceText)
 | 
						else if (portal->sourceText)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		debug_query_string = portal->sourceText;
 | 
							/*
 | 
				
			||||||
		pgstat_report_activity(portal->sourceText);
 | 
							 * We must copy the sourceText into MessageContext in case the
 | 
				
			||||||
 | 
							 * portal is destroyed during finish_xact_command.  Can avoid
 | 
				
			||||||
 | 
							 * the copy if it's not an xact command, though.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (is_xact_command)
 | 
				
			||||||
 | 
								sourceText = pstrdup(portal->sourceText);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								sourceText = portal->sourceText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							debug_query_string = sourceText;
 | 
				
			||||||
 | 
							pgstat_report_activity(sourceText);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1712,12 +1726,11 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
		ResetUsage();
 | 
							ResetUsage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (log_statement == LOGSTMT_ALL)
 | 
						if (log_statement == LOGSTMT_ALL)
 | 
				
			||||||
		/* We have the portal, so output the source query. */
 | 
					 | 
				
			||||||
		ereport(LOG,
 | 
							ereport(LOG,
 | 
				
			||||||
				(errmsg("statement: %sEXECUTE %s  [PREPARE:  %s]",
 | 
									(errmsg("statement: %sEXECUTE %s  [PREPARE:  %s]",
 | 
				
			||||||
						(execute_is_fetch) ? "FETCH from " : "",
 | 
											(execute_is_fetch) ? "FETCH from " : "",
 | 
				
			||||||
						(*portal_name != '\0') ? portal_name : "<unnamed>",
 | 
											(*portal_name != '\0') ? portal_name : "<unnamed>",
 | 
				
			||||||
						portal->sourceText ? portal->sourceText : "")));
 | 
											sourceText ? sourceText : "")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BeginCommand(portal->commandTag, dest);
 | 
						BeginCommand(portal->commandTag, dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1763,7 +1776,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (completed)
 | 
						if (completed)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (IsTransactionStmtList(portal->parseTrees))
 | 
							if (is_xact_command)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * If this was a transaction control statement, commit it.	We
 | 
								 * If this was a transaction control statement, commit it.	We
 | 
				
			||||||
@@ -1828,8 +1841,8 @@ exec_execute_message(const char *portal_name, long max_rows)
 | 
				
			|||||||
								  (stop_t.tv_usec - start_t.tv_usec) / 1000),
 | 
													  (stop_t.tv_usec - start_t.tv_usec) / 1000),
 | 
				
			||||||
							(long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
 | 
												(long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
 | 
				
			||||||
							(execute_is_fetch) ? "FETCH from " : "",
 | 
												(execute_is_fetch) ? "FETCH from " : "",
 | 
				
			||||||
						  (*portal_name != '\0') ? portal_name : "<unnamed>",
 | 
												(*portal_name != '\0') ? portal_name : "<unnamed>",
 | 
				
			||||||
							portal->sourceText ? portal->sourceText : "")));
 | 
												sourceText ? sourceText : "")));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (save_log_statement_stats)
 | 
						if (save_log_statement_stats)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user