Skip site navigation (1) Skip section navigation (2)

Re: Fix issuing of multiple command completions per command

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Fernando Nasser <fnasser(at)redhat(dot)com>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Fix issuing of multiple command completions per command
Date: 2002-02-25 18:34:23
Message-ID: 200202251834.g1PIYN926066@candle.pha.pa.us (view raw or flat)
Thread:
Lists: pgsql-patches
Your patch has been added to the PostgreSQL unapplied patches list at:

	http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Fernando Nasser wrote:
> (Please note that "[PATCHES] Allow arbitrary levels of
> analyze/rewriting"
> must be applied before this patch)
> 
> This patch prevents the issue of multiple command completions
> when queries are rewritten into a sequence queries by analyze/rewrite.
> Currently the front ends are receiving many;  libpq just uses the last
> one received so that is why we see only one response in psql, for 
> instance.
> 
> It fixes a bug where the user receives a bogus completion message 
> for queries that have been turned into a sequence of queries where
> the last one has a different completion tag.
> 
> It also prevents command-completions to be generated by utility commands
> that are inside SQL-functions.
> 
> It also fixes some misplaced calls to set ps_status.
> 
> Furthermore, these changes made possible to reduce the number of
> times ps_status is set (a request from Tom Lane). This is done by
> default but it is still possible to set a compiler flag and have
> it generate more calls as it does today (one for each query produced
> by the rewriting of the original query).
> 
> 
> Here is basically what is done:
> 
> The completion is sent by EndCommand().  This call is used OK by
> plannable queries and is necessary there for telling that the data
> sent to a backend has come to an end.  Utilities, however, don't
> send any data (except FETCH) and may be rewritten into a series of
> other utility queries.  The changes consolidate the calls to
> EndCommand() for utility queries and let the plannable ones 
> handle it pairwise with BeginCommand() (which is not used by
> utility queries).
> 
> 
> ChangeLog:
> 
>         * src/backend/commands/command.c (PerformPortalFetch): Send
>         command completion so that fe knows we are done with sending
> data.
>         * src/backend/commands/explain.c (ExplainOneQuery): Set
> ps_status
>         to EXPLAIN or SELECT (for the EXPLAIN ANALYZE case).  
>         * src/backend/executor/functions.c (postquel_getnext): Do not
> send
>         command completion messages for utilities inside SQL-functions
>         (one will be sent for the command that invoked the function).  
>         * src/backend/executor/spi.c (_SPI_execute, _SPI_execute_plan):
> Add
>         comments.  
>         * src/backend/tcop/postgres.c (pg_exec_query_string):
>         Do not send a command completion message or set the ps_status
> for
>         each utility query that results for the rewriting of a command;
>         just send one for the original command.  Let plannable queries
> take
>         care of their own completion.
>         (CreateCommandTag): New function.  Create a command completion
> tag
>         based on the parse tree node (rather than on an already/analyzed
>         query node).  
>         * src/backend/tcop/utility.c (ProcessUtility): Do
>         not meddle with ps_status or command completion in this
> function.
>         * src/backend/tcop/pquery.c (ProcessQuery): Let the caller set
>         ps_status.
> 
> 
> 
> 
> 
> -- 
> Fernando Nasser
> Red Hat Canada Ltd.                     E-Mail:  fnasser(at)redhat(dot)com
> 2323 Yonge Street, Suite #300
> Toronto, Ontario   M4P 2C9

> Index: src/backend/commands/command.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/commands/command.c,v
> retrieving revision 1.152
> diff -c -p -r1.152 command.c
> *** src/backend/commands/command.c	2002/01/03 23:19:30	1.152
> --- src/backend/commands/command.c	2002/02/14 10:49:18
> *************** PerformPortalFetch(char *name,
> *** 215,231 ****
>   	}
>   
>   	/*
>   	 * Clean up and switch back to old context.
>   	 */
>   	if (temp_desc)
>   		pfree(queryDesc);
>   
>   	MemoryContextSwitchTo(oldcontext);
> - 
> - 	/*
> - 	 * Note: the "end-of-command" tag is returned by higher-level utility
> - 	 * code
> - 	 */
>   }
>   
>   /* --------------------------------
> --- 215,231 ----
>   	}
>   
>   	/*
> + 	 * tell fe/be or whatever that we're done sending the data
> + 	 */
> + 	EndCommand(tag, queryDesc->dest);
> + 
> + 	/*
>   	 * Clean up and switch back to old context.
>   	 */
>   	if (temp_desc)
>   		pfree(queryDesc);
>   
>   	MemoryContextSwitchTo(oldcontext);
>   }
>   
>   /* --------------------------------
> Index: src/backend/commands/explain.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/commands/explain.c,v
> retrieving revision 1.67
> diff -c -p -r1.67 explain.c
> *** src/backend/commands/explain.c	2001/10/25 05:49:25	1.67
> --- src/backend/commands/explain.c	2002/02/14 10:49:18
> ***************
> *** 19,24 ****
> --- 19,25 ----
>   #include "parser/parsetree.h"
>   #include "rewrite/rewriteHandler.h"
>   #include "tcop/pquery.h"
> + #include "utils/ps_status.h"
>   #include "utils/relcache.h"
>   
>   typedef struct ExplainState
> *************** ExplainOneQuery(Query *query, bool verbo
> *** 113,118 ****
> --- 114,121 ----
>   		struct timeval starttime;
>   		struct timeval endtime;
>   
> + 		set_ps_display("SELECT");
> + 		
>   		/*
>   		 * Set up the instrumentation for the top node. This will cascade
>   		 * during plan initialisation
> *************** ExplainOneQuery(Query *query, bool verbo
> *** 133,138 ****
> --- 136,143 ----
>   		}
>   		totaltime = (double) endtime.tv_sec +
>   			(double) endtime.tv_usec / 1000000.0;
> + 			
> + 		set_ps_display("EXPLAIN");
>   	}
>   
>   	es = (ExplainState *) palloc(sizeof(ExplainState));
> Index: src/backend/executor/functions.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/executor/functions.c,v
> retrieving revision 1.47
> diff -c -p -r1.47 functions.c
> *** src/backend/executor/functions.c	2001/10/28 06:25:43	1.47
> --- src/backend/executor/functions.c	2002/02/14 10:49:18
> *************** postquel_getnext(execution_state *es)
> *** 276,281 ****
> --- 276,283 ----
>   		 * Process a utility command. (create, destroy...)	DZ - 30-8-1996
>   		 */
>   		ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest);
> + 		/* We should not call EndCommand() here as we are inside a function
> + 		 * call and command-complete reports should not be issued. */
>   		if (!LAST_POSTQUEL_COMMAND(es))
>   			CommandCounterIncrement();
>   		return (TupleTableSlot *) NULL;
> Index: src/backend/executor/spi.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/executor/spi.c,v
> retrieving revision 1.64
> diff -c -p -r1.64 spi.c
> *** src/backend/executor/spi.c	2002/01/03 20:30:47	1.64
> --- src/backend/executor/spi.c	2002/02/14 10:49:18
> *************** _SPI_execute(char *src, int tcount, _SPI
> *** 1010,1015 ****
> --- 1010,1017 ----
>   			if (plan == NULL)
>   			{
>   				ProcessUtility(queryTree->utilityStmt, None);
> + 				/* We don't need to call EndCommand() as we don't want to
> + 				 * send anything (dest = None) */
>   				if (!islastquery)
>   					CommandCounterIncrement();
>   				else
> *************** _SPI_execute_plan(_SPI_plan *plan, Datum
> *** 1084,1089 ****
> --- 1086,1093 ----
>   		if (queryTree->commandType == CMD_UTILITY)
>   		{
>   			ProcessUtility(queryTree->utilityStmt, None);
> + 			/* We don't need to call EndCommand() as we don't want to
> + 			 * send anything (dest = None) */
>   			if (!islastquery)
>   				CommandCounterIncrement();
>   			else
> Index: src/backend/parser/analyze.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/parser/analyze.c,v
> retrieving revision 1.213
> diff -c -p -r1.213 analyze.c
> *** src/backend/parser/analyze.c	2002/01/03 23:21:31	1.213
> --- src/backend/parser/analyze.c	2002/02/14 10:49:18
> *************** typedef struct
> *** 64,80 ****
>   } CreateStmtContext;
>   
>   
> ! static Query *transformStmt(ParseState *pstate, Node *stmt);
>   static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
> ! static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
>   static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
> ! static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
>   static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
>   static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
>   static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
>   static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
> ! static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
> ! static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
>   static void transformColumnDefinition(ParseState *pstate,
>   						  CreateStmtContext *cxt,
>   						  ColumnDef *column);
> --- 64,85 ----
>   } CreateStmtContext;
>   
>   
> ! static Query *transformStmt(ParseState *pstate, Node *stmt,
> ! 						List **extras_before, List **extras_after);
>   static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
> ! static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
> ! 						List **extras_before, List **extras_after);
>   static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
> ! static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt,
> ! 						List **extras_before, List **extras_after);
>   static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
>   static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
>   static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
>   static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
> ! static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
> ! 						List **extras_before, List **extras_after);
> ! static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
> ! 						List **extras_before, List **extras_after);
>   static void transformColumnDefinition(ParseState *pstate,
>   						  CreateStmtContext *cxt,
>   						  ColumnDef *column);
> *************** static Oid	transformFkeyGetColType(Creat
> *** 101,109 ****
>   static void release_pstate_resources(ParseState *pstate);
>   static FromExpr *makeFromExpr(List *fromlist, Node *quals);
>   
> - /* kluge to return extra info from transformCreateStmt() */
> - static List *extras_before;
> - static List *extras_after;
>   
>   
>   /*
> --- 106,111 ----
> *************** parse_analyze(Node *parseTree, ParseStat
> *** 121,137 ****
>   	List	   *result = NIL;
>   	ParseState *pstate = make_parsestate(parentParseState);
>   	Query	   *query;
>   
> ! 	extras_before = extras_after = NIL;
> ! 
> ! 	query = transformStmt(pstate, parseTree);
>   	release_pstate_resources(pstate);
> ! 
>   	while (extras_before != NIL)
>   	{
> ! 		result = lappend(result,
> ! 						 transformStmt(pstate, lfirst(extras_before)));
> ! 		release_pstate_resources(pstate);
>   		extras_before = lnext(extras_before);
>   	}
>   
> --- 123,138 ----
>   	List	   *result = NIL;
>   	ParseState *pstate = make_parsestate(parentParseState);
>   	Query	   *query;
> + 	/* Lists to return extra commands from transformation */
> + 	List *extras_before = NIL;
> + 	List *extras_after = NIL;
>   
> ! 	query = transformStmt(pstate, parseTree, &extras_before, &extras_after);
>   	release_pstate_resources(pstate);
> ! 	
>   	while (extras_before != NIL)
>   	{
> ! 		result = nconc(result, parse_analyze(lfirst(extras_before), pstate));
>   		extras_before = lnext(extras_before);
>   	}
>   
> *************** parse_analyze(Node *parseTree, ParseStat
> *** 139,147 ****
>   
>   	while (extras_after != NIL)
>   	{
> ! 		result = lappend(result,
> ! 						 transformStmt(pstate, lfirst(extras_after)));
> ! 		release_pstate_resources(pstate);
>   		extras_after = lnext(extras_after);
>   	}
>   
> --- 140,146 ----
>   
>   	while (extras_after != NIL)
>   	{
> ! 		result = nconc(result, parse_analyze(lfirst(extras_after), pstate));
>   		extras_after = lnext(extras_after);
>   	}
>   
> *************** release_pstate_resources(ParseState *pst
> *** 164,170 ****
>    *	  transform a Parse tree into a Query tree.
>    */
>   static Query *
> ! transformStmt(ParseState *pstate, Node *parseTree)
>   {
>   	Query	   *result = NULL;
>   
> --- 163,170 ----
>    *	  transform a Parse tree into a Query tree.
>    */
>   static Query *
> ! transformStmt(ParseState *pstate, Node *parseTree,
> ! 			  List **extras_before,	List **extras_after)
>   {
>   	Query	   *result = NULL;
>   
> *************** transformStmt(ParseState *pstate, Node *
> *** 174,180 ****
>   			 * Non-optimizable statements
>   			 */
>   		case T_CreateStmt:
> ! 			result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
>   			break;
>   
>   		case T_IndexStmt:
> --- 174,181 ----
>   			 * Non-optimizable statements
>   			 */
>   		case T_CreateStmt:
> ! 			result = transformCreateStmt(pstate, (CreateStmt *) parseTree,
> ! 									extras_before, extras_after);
>   			break;
>   
>   		case T_IndexStmt:
> *************** transformStmt(ParseState *pstate, Node *
> *** 182,195 ****
>   			break;
>   
>   		case T_RuleStmt:
> ! 			result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
>   			break;
>   
>   		case T_ViewStmt:
>   			{
>   				ViewStmt   *n = (ViewStmt *) parseTree;
>   
> ! 				n->query = transformStmt(pstate, (Node *) n->query);
>   
>   				/*
>   				 * If a list of column names was given, run through and
> --- 183,198 ----
>   			break;
>   
>   		case T_RuleStmt:
> ! 			result = transformRuleStmt(pstate, (RuleStmt *) parseTree,
> ! 									extras_before, extras_after);
>   			break;
>   
>   		case T_ViewStmt:
>   			{
>   				ViewStmt   *n = (ViewStmt *) parseTree;
>   
> ! 				n->query = transformStmt(pstate, (Node *) n->query,
> ! 									extras_before, extras_after);
>   
>   				/*
>   				 * If a list of column names was given, run through and
> *************** transformStmt(ParseState *pstate, Node *
> *** 239,258 ****
>   
>   				result = makeNode(Query);
>   				result->commandType = CMD_UTILITY;
> ! 				n->query = transformStmt(pstate, (Node *) n->query);
>   				result->utilityStmt = (Node *) parseTree;
>   			}
>   			break;
>   
>   		case T_AlterTableStmt:
> ! 			result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
>   			break;
>   
>   			/*
>   			 * Optimizable statements
>   			 */
>   		case T_InsertStmt:
> ! 			result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
>   			break;
>   
>   		case T_DeleteStmt:
> --- 242,264 ----
>   
>   				result = makeNode(Query);
>   				result->commandType = CMD_UTILITY;
> ! 				n->query = transformStmt(pstate, (Node *) n->query,
> ! 								extras_before, extras_after);
>   				result->utilityStmt = (Node *) parseTree;
>   			}
>   			break;
>   
>   		case T_AlterTableStmt:
> ! 			result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree,
> ! 										extras_before, extras_after);
>   			break;
>   
>   			/*
>   			 * Optimizable statements
>   			 */
>   		case T_InsertStmt:
> ! 			result = transformInsertStmt(pstate, (InsertStmt *) parseTree,
> ! 										extras_before, extras_after);
>   			break;
>   
>   		case T_DeleteStmt:
> *************** transformDeleteStmt(ParseState *pstate, 
> *** 337,343 ****
>    *	  transform an Insert Statement
>    */
>   static Query *
> ! transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
>   {
>   	Query	   *qry = makeNode(Query);
>   	List	   *sub_rtable;
> --- 343,350 ----
>    *	  transform an Insert Statement
>    */
>   static Query *
> ! transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
> ! 					List **extras_before, List **extras_after)
>   {
>   	Query	   *qry = makeNode(Query);
>   	List	   *sub_rtable;
> *************** transformInsertStmt(ParseState *pstate, 
> *** 402,408 ****
>   		sub_pstate->p_rtable = sub_rtable;
>   		sub_pstate->p_namespace = sub_namespace;
>   
> ! 		selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
>   
>   		release_pstate_resources(sub_pstate);
>   		pfree(sub_pstate);
> --- 409,420 ----
>   		sub_pstate->p_rtable = sub_rtable;
>   		sub_pstate->p_namespace = sub_namespace;
>   
> ! 		/*
> ! 		 * Note: we are not expecting that extras_before and extras_after
> ! 		 * are going to be used by the transformation of the SELECT statement.
> !  		 */
> ! 		selectQuery = transformStmt(sub_pstate, stmt->selectStmt,
> ! 								extras_before, extras_after);
>   
>   		release_pstate_resources(sub_pstate);
>   		pfree(sub_pstate);
> *************** CreateIndexName(char *table_name, char *
> *** 658,664 ****
>    *	  - thomas 1997-12-02
>    */
>   static Query *
> ! transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
>   {
>   	CreateStmtContext cxt;
>   	Query	   *q;
> --- 670,677 ----
>    *	  - thomas 1997-12-02
>    */
>   static Query *
> ! transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
> ! 					List **extras_before, List **extras_after)
>   {
>   	CreateStmtContext cxt;
>   	Query	   *q;
> *************** transformCreateStmt(ParseState *pstate, 
> *** 728,735 ****
>   	q->utilityStmt = (Node *) stmt;
>   	stmt->tableElts = cxt.columns;
>   	stmt->constraints = cxt.ckconstraints;
> ! 	extras_before = cxt.blist;
> ! 	extras_after = cxt.alist;
>   
>   	return q;
>   }
> --- 741,748 ----
>   	q->utilityStmt = (Node *) stmt;
>   	stmt->tableElts = cxt.columns;
>   	stmt->constraints = cxt.ckconstraints;
> ! 	*extras_before = nconc (*extras_before, cxt.blist);
> ! 	*extras_after = nconc (cxt.alist, *extras_after);
>   
>   	return q;
>   }
> *************** transformIndexStmt(ParseState *pstate, I
> *** 1668,1674 ****
>    *	  trees which is transformed into a list of query trees.
>    */
>   static Query *
> ! transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
>   {
>   	Query	   *qry;
>   	RangeTblEntry *oldrte;
> --- 1681,1688 ----
>    *	  trees which is transformed into a list of query trees.
>    */
>   static Query *
> ! transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
> ! 				List **extras_before, List **extras_after)
>   {
>   	Query	   *qry;
>   	RangeTblEntry *oldrte;
> *************** transformRuleStmt(ParseState *pstate, Ru
> *** 1797,1803 ****
>   			addRTEtoQuery(sub_pstate, newrte, false, true);
>   
>   			/* Transform the rule action statement */
> ! 			top_subqry = transformStmt(sub_pstate, action);
>   
>   			/*
>   			 * We cannot support utility-statement actions (eg NOTIFY)
> --- 1811,1818 ----
>   			addRTEtoQuery(sub_pstate, newrte, false, true);
>   
>   			/* Transform the rule action statement */
> ! 			top_subqry = transformStmt(sub_pstate, action,
> ! 								extras_before, extras_after);
>   
>   			/*
>   			 * We cannot support utility-statement actions (eg NOTIFY)
> *************** transformUpdateStmt(ParseState *pstate, 
> *** 2494,2500 ****
>    *	transform an Alter Table Statement
>    */
>   static Query *
> ! transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
>   {
>   	CreateStmtContext cxt;
>   	Query	   *qry;
> --- 2509,2516 ----
>    *	transform an Alter Table Statement
>    */
>   static Query *
> ! transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
> ! 						List **extras_before, List **extras_after)
>   {
>   	CreateStmtContext cxt;
>   	Query	   *qry;
> *************** transformAlterTableStmt(ParseState *psta
> *** 2534,2541 ****
>   			transformFKConstraints(pstate, &cxt);
>   
>   			((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints;
> ! 			extras_before = cxt.blist;
> ! 			extras_after = cxt.alist;
>   			break;
>   
>   		case 'C':
> --- 2550,2557 ----
>   			transformFKConstraints(pstate, &cxt);
>   
>   			((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints;
> ! 			*extras_before = nconc(*extras_before, cxt.blist);
> ! 			*extras_after = nconc(cxt.alist, *extras_after);
>   			break;
>   
>   		case 'C':
> *************** transformAlterTableStmt(ParseState *psta
> *** 2571,2578 ****
>   
>   			Assert(cxt.columns == NIL);
>   			stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints);
> ! 			extras_before = cxt.blist;
> ! 			extras_after = cxt.alist;
>   			break;
>   
>   		default:
> --- 2587,2594 ----
>   
>   			Assert(cxt.columns == NIL);
>   			stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints);
> ! 			*extras_before = nconc(*extras_before, cxt.blist);
> ! 			*extras_after = nconc(cxt.alist, *extras_after);
>   			break;
>   
>   		default:
> Index: src/backend/tcop/postgres.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/tcop/postgres.c,v
> retrieving revision 1.245
> diff -c -p -r1.245 postgres.c
> *** src/backend/tcop/postgres.c	2002/01/10 01:11:45	1.245
> --- src/backend/tcop/postgres.c	2002/02/14 10:49:19
> ***************
> *** 64,69 ****
> --- 64,78 ----
>   
>   #include "pgstat.h"
>   
> + static char *CreateCommandTag(Node *parsetree);
> + 
> + /* Uncomment the following line if you want ps_status
> +  * to be set for each individual query that may result from
> +  * a rewrite as oposed to just the main (original) one
> +  */
> + /* #define FINE_GRAIN_PROFILE 1 */
> + 
> + 
>   /* ----------------
>    *		global variables
>    * ----------------
> *************** pg_exec_query_string(char *query_string,
> *** 634,639 ****
> --- 643,650 ----
>   	foreach(parsetree_item, parsetree_list)
>   	{
>   		Node	   *parsetree = (Node *) lfirst(parsetree_item);
> + 		char	   *commandTag = NULL;
> + 		bool		isQueryStmt = false;
>   		bool		isTransactionStmt;
>   		List	   *querytree_list,
>   				   *querytree_item;
> *************** pg_exec_query_string(char *query_string,
> *** 675,680 ****
> --- 686,693 ----
>   				 * command ended. -cim 6/1/90
>   				 */
>   				char	   *tag = "*ABORT STATE*";
> + 				
> + 				set_ps_display(tag);
>   
>   				elog(NOTICE, "current transaction is aborted, "
>   					 "queries ignored until end of transaction block");
> *************** pg_exec_query_string(char *query_string,
> *** 702,708 ****
>   
>   		/*
>   		 * OK to analyze and rewrite this query.
> ! 		 *
>   		 * Switch to appropriate context for constructing querytrees (again,
>   		 * these must outlive the execution context).
>   		 */
> --- 715,737 ----
>   
>   		/*
>   		 * OK to analyze and rewrite this query.
> ! 		 */
> ! 		 
> ! 		/*
> ! 		 * First we set the command-completion tag to the main query
> ! 		 * (as opposed to each of the others that may have
> ! 		 * been generated by analyze and rewrite)
> ! 		 */
> ! 		commandTag = CreateCommandTag(parsetree);
> ! 
> ! #ifndef FINE_GRAIN_PROFILE
> ! 		/*
> ! 		 * Set ps_status to the main query tag
> ! 		 */
> ! 		set_ps_display(commandTag);
> ! #endif
> ! 		 
> ! 		/*
>   		 * Switch to appropriate context for constructing querytrees (again,
>   		 * these must outlive the execution context).
>   		 */
> *************** pg_exec_query_string(char *query_string,
> *** 746,752 ****
> --- 775,796 ----
>   				else if (DebugLvl > 1)
>   					elog(DEBUG, "ProcessUtility");
>   
> + #ifdef FINE_GRAIN_PROFILE
> + 				set_ps_display(CreateUtilityTag(querytree->utilityStmt));
> + #endif
>   				ProcessUtility(querytree->utilityStmt, dest);
> + 
> + 				/*
> + 				 * FETCHes, as plannable queries, take care of completion
> + 				 * themselves but we still have to do it for MOVEs as they
> + 				 * do not send data (and thus, do not send a completion).
> + 				 */
> + 				if (nodeTag(parsetree) == T_FetchStmt)
> + 				{
> + 					FetchStmt  *stmt = (FetchStmt *) parsetree;
> + 					if (!(stmt->ismove))
> + 						isQueryStmt = true;  /* Don't do it twice */
> + 				}
>   			}
>   			else
>   			{
> *************** pg_exec_query_string(char *query_string,
> *** 754,759 ****
> --- 798,805 ----
>   				 * process a plannable query.
>   				 */
>   				Plan	   *plan;
> + 				
> + 				isQueryStmt = true;
>   
>   				plan = pg_plan_query(querytree);
>   
> *************** pg_exec_query_string(char *query_string,
> *** 818,823 ****
> --- 864,876 ----
>   
>   		}						/* end loop over queries generated from a
>   								 * parsetree */
> + 
> + 		/*
> + 		 * tell fe/be or whatever that we're done if we only processed
> + 		 * utilities (plannable queries take care of completion themselves)
> + 		 */
> + 		if (!isQueryStmt)
> + 			EndCommand(commandTag, dest);
>   	}							/* end loop over parsetrees */
>   
>   	/*
> *************** assertTest(int val)
> *** 2037,2039 ****
> --- 2090,2354 ----
>   #endif
>   
>   #endif
> + 
> + 
> + /* ----------------------------------------------------------------
> +  *		CreateCommandTag
> +  *
> +  *		utility to get a string representation of the
> +  *		command operation.
> +  * ----------------------------------------------------------------
> +  */
> + static char *
> + CreateCommandTag(Node *parsetree)
> + {
> + 	char	   *tag = NULL;
> + 
> + 	switch (nodeTag(parsetree))
> + 	{
> + 		case T_InsertStmt:
> + 			tag = "INSERT";
> + 			break;
> + 
> + 		case T_DeleteStmt:
> + 			tag = "DELETE";
> + 			break;
> + 
> + 		case T_UpdateStmt:
> + 			tag = "UPDATE";
> + 			break;
> + 
> + 		case T_SelectStmt:
> + 			tag = "SELECT";
> + 			break;
> + 
> + 		case T_TransactionStmt:
> + 			{
> + 				TransactionStmt *stmt = (TransactionStmt *) parsetree;
> + 
> + 				switch (stmt->command)
> + 				{
> + 					case BEGIN_TRANS:
> + 						tag = "BEGIN";
> + 						break;
> + 
> + 					case COMMIT:
> + 						tag = "COMMIT";
> + 						break;
> + 
> + 					case ROLLBACK:
> + 						tag = "ROLLBACK";
> + 						break;
> + 				}
> + 			}
> + 			break;
> + 
> + 		case T_ClosePortalStmt:
> + 			tag = "CLOSE";
> + 			break;
> + 
> + 		case T_FetchStmt:
> + 			{
> + 				FetchStmt  *stmt = (FetchStmt *) parsetree;
> + 				tag = (stmt->ismove) ? "MOVE" : "FETCH";
> + 			}
> + 			break;
> + 
> + 		case T_CreateStmt:
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_DropStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_TruncateStmt:
> + 			tag = "TRUNCATE";
> + 			break;
> + 
> + 		case T_CommentStmt:
> + 			tag = "COMMENT";
> + 			break;
> + 
> + 		case T_CopyStmt:
> + 			tag = "COPY";
> + 			break;
> + 
> + 		case T_RenameStmt:
> + 			tag = "ALTER";
> + 			break;
> + 
> + 		case T_AlterTableStmt:
> + 			tag = "ALTER";
> + 			break;
> + 
> + 		case T_GrantStmt:
> + 			{
> + 				GrantStmt  *stmt = (GrantStmt *) parsetree;
> + 				tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
> + 			}
> + 			break;
> + 
> + 		case T_DefineStmt:
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_ViewStmt:		/* CREATE VIEW */
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_ProcedureStmt:	/* CREATE FUNCTION */
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_IndexStmt:		/* CREATE INDEX */
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_RuleStmt:		/* CREATE RULE */
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_CreateSeqStmt:
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_RemoveAggrStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_RemoveFuncStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_RemoveOperStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_VersionStmt:
> + 			tag = "CREATE VERSION";
> + 			break;
> + 
> + 		case T_CreatedbStmt:
> + 			tag = "CREATE DATABASE";
> + 			break;
> + 
> + 		case T_DropdbStmt:
> + 			tag = "DROP DATABASE";
> + 			break;
> + 
> + 		case T_NotifyStmt:
> + 			tag = "NOTIFY";
> + 			break;
> + 
> + 		case T_ListenStmt:
> + 			tag = "LISTEN";
> + 			break;
> + 
> + 		case T_UnlistenStmt:
> + 			tag = "UNLISTEN";
> + 			break;
> + 
> + 		case T_LoadStmt:
> + 			tag = "LOAD";
> + 			break;
> + 
> + 		case T_ClusterStmt:
> + 			tag = "CLUSTER";
> + 			break;
> + 
> + 		case T_VacuumStmt:
> + 			if (((VacuumStmt *) parsetree)->vacuum)
> + 				tag = "VACUUM";
> + 			else
> + 				tag = "ANALYZE";
> + 			break;
> + 
> + 		case T_ExplainStmt:
> + 			tag = "EXPLAIN";
> + 			break;
> + 
> + #ifdef NOT_USED
> + 		case T_RecipeStmt:
> + 			tag = "EXECUTE RECIPE";
> + 			break;
> + #endif
> + 
> + 		case T_VariableSetStmt:
> + 			tag = "SET VARIABLE";
> + 			break;
> + 
> + 		case T_VariableShowStmt:
> + 			tag = "SHOW VARIABLE";
> + 			break;
> + 
> + 		case T_VariableResetStmt:
> + 			tag = "RESET VARIABLE";
> + 			break;
> + 
> + 		case T_CreateTrigStmt:
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_DropTrigStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_CreatePLangStmt:
> + 			tag = "CREATE";
> + 			break;
> + 
> + 		case T_DropPLangStmt:
> + 			tag = "DROP";
> + 			break;
> + 
> + 		case T_CreateUserStmt:
> + 			tag = "CREATE USER";
> + 			break;
> + 
> + 		case T_AlterUserStmt:
> + 			tag = "ALTER USER";
> + 			break;
> + 
> + 		case T_DropUserStmt:
> + 			tag = "DROP USER";
> + 			break;
> + 
> + 		case T_LockStmt:
> + 			tag = "LOCK TABLE";
> + 			break;
> + 
> + 		case T_ConstraintsSetStmt:
> + 			tag = "SET CONSTRAINTS";
> + 			break;
> + 
> + 		case T_CreateGroupStmt:
> + 			tag = "CREATE GROUP";
> + 			break;
> + 
> + 		case T_AlterGroupStmt:
> + 			tag = "ALTER GROUP";
> + 			break;
> + 
> + 		case T_DropGroupStmt:
> + 			tag = "DROP GROUP";
> + 			break;
> + 
> + 		case T_CheckPointStmt:
> + 			tag = "CHECKPOINT";
> + 			break;
> + 
> + 		case T_ReindexStmt:
> + 			tag = "REINDEX";
> + 			break;
> + 
> + 		default:
> + 			elog(DEBUG, "CreateUtilityTag: unknown utility operation type %d",
> + 	 			nodeTag(parsetree));
> + 			tag = "???";
> + 			break;
> + 	}
> + 
> + 	return tag;
> + }
> + 
> Index: src/backend/tcop/pquery.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/tcop/pquery.c,v
> retrieving revision 1.46
> diff -c -p -r1.46 pquery.c
> *** src/backend/tcop/pquery.c	2001/10/25 05:49:43	1.46
> --- src/backend/tcop/pquery.c	2002/02/14 10:49:19
> *************** ProcessQuery(Query *parsetree,
> *** 180,186 ****
>   	EState	   *state;
>   	TupleDesc	attinfo;
>   
> ! 	set_ps_display(tag = CreateOperationTag(operation));
>   
>   	/*
>   	 * initialize portal/into relation status
> --- 180,186 ----
>   	EState	   *state;
>   	TupleDesc	attinfo;
>   
> ! 	tag = CreateOperationTag(operation);
>   
>   	/*
>   	 * initialize portal/into relation status
> Index: src/backend/tcop/utility.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v
> retrieving revision 1.125
> diff -c -p -r1.125 utility.c
> *** src/backend/tcop/utility.c	2002/02/07 00:27:30	1.125
> --- src/backend/tcop/utility.c	2002/02/14 10:49:19
> ***************
> *** 44,54 ****
>   #include "rewrite/rewriteRemove.h"
>   #include "tcop/utility.h"
>   #include "utils/acl.h"
> - #include "utils/ps_status.h"
>   #include "utils/syscache.h"
>   #include "utils/temprel.h"
>   #include "access/xlog.h"
>   
>   /*
>    * Error-checking support for DROP commands
>    */
> --- 44,54 ----
>   #include "rewrite/rewriteRemove.h"
>   #include "tcop/utility.h"
>   #include "utils/acl.h"
>   #include "utils/syscache.h"
>   #include "utils/temprel.h"
>   #include "access/xlog.h"
>   
> + 
>   /*
>    * Error-checking support for DROP commands
>    */
> *************** CheckDropPermissions(char *name, char ri
> *** 132,144 ****
>   
>   /* ----------------
>    *		general utility function invoker
>    * ----------------
>    */
>   void
>   ProcessUtility(Node *parsetree,
>   			   CommandDest dest)
>   {
> - 	char	   *commandTag = NULL;
>   	char	   *relname;
>   	char	   *relationName;
>   
> --- 132,145 ----
>   
>   /* ----------------
>    *		general utility function invoker
> +  *
> +  *	Returns the command-complete tag appropriate for the function
>    * ----------------
>    */
>   void
>   ProcessUtility(Node *parsetree,
>   			   CommandDest dest)
>   {
>   	char	   *relname;
>   	char	   *relationName;
>   
> *************** ProcessUtility(Node *parsetree,
> *** 155,171 ****
>   				switch (stmt->command)
>   				{
>   					case BEGIN_TRANS:
> - 						set_ps_display(commandTag = "BEGIN");
>   						BeginTransactionBlock();
>   						break;
>   
>   					case COMMIT:
> - 						set_ps_display(commandTag = "COMMIT");
>   						EndTransactionBlock();
>   						break;
>   
>   					case ROLLBACK:
> - 						set_ps_display(commandTag = "ROLLBACK");
>   						UserAbortTransactionBlock();
>   						break;
>   				}
> --- 156,169 ----
> *************** ProcessUtility(Node *parsetree,
> *** 180,187 ****
>   			{
>   				ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CLOSE");
> - 
>   				PerformPortalClose(stmt->portalname, dest);
>   			}
>   			break;
> --- 178,183 ----
> *************** ProcessUtility(Node *parsetree,
> *** 193,200 ****
>   				bool		forward;
>   				int			count;
>   
> - 				set_ps_display(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
> - 
>   				SetQuerySnapshot();
>   
>   				forward = (bool) (stmt->direction == FORWARD);
> --- 189,194 ----
> *************** ProcessUtility(Node *parsetree,
> *** 204,210 ****
>   				 */
>   
>   				count = stmt->howMany;
> ! 				PerformPortalFetch(portalName, forward, count, commandTag,
>   								   (stmt->ismove) ? None : dest);		/* /dev/null for MOVE */
>   			}
>   			break;
> --- 198,204 ----
>   				 */
>   
>   				count = stmt->howMany;
> ! 				PerformPortalFetch(portalName, forward, count,(stmt->ismove) ? "MOVE" : "FETCH",
>   								   (stmt->ismove) ? None : dest);		/* /dev/null for MOVE */
>   			}
>   			break;
> *************** ProcessUtility(Node *parsetree,
> *** 215,222 ****
>   			 *
>   			 */
>   		case T_CreateStmt:
> - 			set_ps_display(commandTag = "CREATE");
> - 
>   			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
>   
>   			/*
> --- 209,214 ----
> *************** ProcessUtility(Node *parsetree,
> *** 234,241 ****
>   				List	   *args = stmt->names;
>   				List	   *arg;
>   
> - 				set_ps_display(commandTag = "DROP");
> - 
>   				foreach(arg, args)
>   				{
>   					relname = strVal(lfirst(arg));
> --- 226,231 ----
> *************** ProcessUtility(Node *parsetree,
> *** 296,303 ****
>   			{
>   				Relation	rel;
>   
> - 				set_ps_display(commandTag = "TRUNCATE");
> - 
>   				relname = ((TruncateStmt *) parsetree)->relName;
>   				if (!allowSystemTableMods && IsSystemRelationName(relname))
>   					elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
> --- 286,291 ----
> *************** ProcessUtility(Node *parsetree,
> *** 325,332 ****
>   
>   				statement = ((CommentStmt *) parsetree);
>   
> - 				set_ps_display(commandTag = "COMMENT");
> - 
>   				CommentObject(statement->objtype, statement->objname,
>   							  statement->objproperty, statement->objlist,
>   							  statement->comment);
> --- 313,318 ----
> *************** ProcessUtility(Node *parsetree,
> *** 337,344 ****
>   			{
>   				CopyStmt   *stmt = (CopyStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "COPY");
> - 
>   				if (stmt->direction != FROM)
>   					SetQuerySnapshot();
>   
> --- 323,328 ----
> *************** ProcessUtility(Node *parsetree,
> *** 365,372 ****
>   			{
>   				RenameStmt *stmt = (RenameStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "ALTER");
> - 
>   				relname = stmt->relname;
>   				if (!allowSystemTableMods && IsSystemRelationName(relname))
>   					elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
> --- 349,354 ----
> *************** ProcessUtility(Node *parsetree,
> *** 413,420 ****
>   			{
>   				AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "ALTER");
> - 
>   				/*
>   				 * Some or all of these functions are recursive to cover
>   				 * inherited things, so permission checks are done there.
> --- 395,400 ----
> *************** ProcessUtility(Node *parsetree,
> *** 475,483 ****
>   			{
>   				GrantStmt  *stmt = (GrantStmt *) parsetree;
>   
> - 				commandTag = stmt->is_grant ? "GRANT" : "REVOKE";
> - 				set_ps_display(commandTag);
> - 
>   				ExecuteGrantStmt(stmt);
>   			}
>   			break;
> --- 455,460 ----
> *************** ProcessUtility(Node *parsetree,
> *** 491,498 ****
>   			{
>   				DefineStmt *stmt = (DefineStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CREATE");
> - 
>   				switch (stmt->defType)
>   				{
>   					case OPERATOR:
> --- 468,473 ----
> *************** ProcessUtility(Node *parsetree,
> *** 514,528 ****
>   			{
>   				ViewStmt   *stmt = (ViewStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CREATE");
> - 
>   				DefineView(stmt->viewname, stmt->query);		/* retrieve parsetree */
>   			}
>   			break;
>   
>   		case T_ProcedureStmt:	/* CREATE FUNCTION */
> - 			set_ps_display(commandTag = "CREATE");
> - 
>   			CreateFunction((ProcedureStmt *) parsetree);
>   			break;
>   
> --- 489,499 ----
> *************** ProcessUtility(Node *parsetree,
> *** 530,537 ****
>   			{
>   				IndexStmt  *stmt = (IndexStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CREATE");
> - 
>   				relname = stmt->relname;
>   				if (!allowSystemTableMods && IsSystemRelationName(relname))
>   					elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
> --- 501,506 ----
> *************** ProcessUtility(Node *parsetree,
> *** 559,573 ****
>   				aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
>   				if (aclcheck_result != ACLCHECK_OK)
>   					elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
> - 				set_ps_display(commandTag = "CREATE");
>   
>   				DefineQueryRewrite(stmt);
>   			}
>   			break;
>   
>   		case T_CreateSeqStmt:
> - 			set_ps_display(commandTag = "CREATE");
> - 
>   			DefineSequence((CreateSeqStmt *) parsetree);
>   			break;
>   
> --- 528,539 ----
> *************** ProcessUtility(Node *parsetree,
> *** 576,583 ****
>   				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
>   				char	   *typename = (char *) NULL;
>   
> - 				set_ps_display(commandTag = "DROP");
> - 
>   				if (stmt->aggtype != NULL)
>   					typename = TypeNameToInternalName((TypeName *) stmt->aggtype);
>   
> --- 542,547 ----
> *************** ProcessUtility(Node *parsetree,
> *** 589,596 ****
>   			{
>   				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "DROP");
> - 
>   				RemoveFunction(stmt->funcname, stmt->args);
>   			}
>   			break;
> --- 553,558 ----
> *************** ProcessUtility(Node *parsetree,
> *** 603,610 ****
>   				char	   *typename1 = (char *) NULL;
>   				char	   *typename2 = (char *) NULL;
>   
> - 				set_ps_display(commandTag = "DROP");
> - 
>   				if (typenode1 != NULL)
>   					typename1 = TypeNameToInternalName(typenode1);
>   				if (typenode2 != NULL)
> --- 565,570 ----
> *************** ProcessUtility(Node *parsetree,
> *** 622,629 ****
>   			{
>   				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CREATE DATABASE");
> - 
>   				createdb(stmt->dbname, stmt->dbpath,
>   						 stmt->dbtemplate, stmt->encoding);
>   			}
> --- 582,587 ----
> *************** ProcessUtility(Node *parsetree,
> *** 633,640 ****
>   			{
>   				DropdbStmt *stmt = (DropdbStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "DROP DATABASE");
> - 
>   				dropdb(stmt->dbname);
>   			}
>   			break;
> --- 591,596 ----
> *************** ProcessUtility(Node *parsetree,
> *** 644,651 ****
>   			{
>   				NotifyStmt *stmt = (NotifyStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "NOTIFY");
> - 
>   				Async_Notify(stmt->relname);
>   			}
>   			break;
> --- 600,605 ----
> *************** ProcessUtility(Node *parsetree,
> *** 654,661 ****
>   			{
>   				ListenStmt *stmt = (ListenStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "LISTEN");
> - 
>   				Async_Listen(stmt->relname, MyProcPid);
>   			}
>   			break;
> --- 608,613 ----
> *************** ProcessUtility(Node *parsetree,
> *** 664,671 ****
>   			{
>   				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "UNLISTEN");
> - 
>   				Async_Unlisten(stmt->relname, MyProcPid);
>   			}
>   			break;
> --- 616,621 ----
> *************** ProcessUtility(Node *parsetree,
> *** 678,685 ****
>   			{
>   				LoadStmt   *stmt = (LoadStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "LOAD");
> - 
>   				closeAllVfds(); /* probably not necessary... */
>   				load_file(stmt->filename);
>   			}
> --- 628,633 ----
> *************** ProcessUtility(Node *parsetree,
> *** 689,696 ****
>   			{
>   				ClusterStmt *stmt = (ClusterStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "CLUSTER");
> - 
>   				relname = stmt->relname;
>   				if (IsSystemRelationName(relname))
>   					elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
> --- 637,642 ----
> *************** ProcessUtility(Node *parsetree,
> *** 703,714 ****
>   			break;
>   
>   		case T_VacuumStmt:
> - 			if (((VacuumStmt *) parsetree)->vacuum)
> - 				commandTag = "VACUUM";
> - 			else
> - 				commandTag = "ANALYZE";
> - 			set_ps_display(commandTag);
> - 
>   			vacuum((VacuumStmt *) parsetree);
>   			break;
>   
> --- 649,654 ----
> *************** ProcessUtility(Node *parsetree,
> *** 716,723 ****
>   			{
>   				ExplainStmt *stmt = (ExplainStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "EXPLAIN");
> - 
>   				ExplainQuery(stmt->query, stmt->verbose, stmt->analyze, dest);
>   			}
>   			break;
> --- 656,661 ----
> *************** ProcessUtility(Node *parsetree,
> *** 731,738 ****
>   			{
>   				RecipeStmt *stmt = (RecipeStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "EXECUTE RECIPE");
> - 
>   				beginRecipe(stmt);
>   			}
>   			break;
> --- 669,674 ----
> *************** ProcessUtility(Node *parsetree,
> *** 746,752 ****
>   				VariableSetStmt *n = (VariableSetStmt *) parsetree;
>   
>   				SetPGVariable(n->name, n->args);
> - 				set_ps_display(commandTag = "SET VARIABLE");
>   			}
>   			break;
>   
> --- 682,687 ----
> *************** ProcessUtility(Node *parsetree,
> *** 755,761 ****
>   				VariableShowStmt *n = (VariableShowStmt *) parsetree;
>   
>   				GetPGVariable(n->name);
> - 				set_ps_display(commandTag = "SHOW VARIABLE");
>   			}
>   			break;
>   
> --- 690,695 ----
> *************** ProcessUtility(Node *parsetree,
> *** 764,770 ****
>   				VariableResetStmt *n = (VariableResetStmt *) parsetree;
>   
>   				ResetPGVariable(n->name);
> - 				set_ps_display(commandTag = "RESET VARIABLE");
>   			}
>   			break;
>   
> --- 698,703 ----
> *************** ProcessUtility(Node *parsetree,
> *** 772,785 ****
>   			 * ******************************** TRIGGER statements *******************************
>   			 */
>   		case T_CreateTrigStmt:
> - 			set_ps_display(commandTag = "CREATE");
> - 
>   			CreateTrigger((CreateTrigStmt *) parsetree);
>   			break;
>   
>   		case T_DropTrigStmt:
> - 			set_ps_display(commandTag = "DROP");
> - 
>   			DropTrigger((DropTrigStmt *) parsetree);
>   			break;
>   
> --- 705,714 ----
> *************** ProcessUtility(Node *parsetree,
> *** 787,800 ****
>   			 * ************* PROCEDURAL LANGUAGE statements *****************
>   			 */
>   		case T_CreatePLangStmt:
> - 			set_ps_display(commandTag = "CREATE");
> - 
>   			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
>   			break;
>   
>   		case T_DropPLangStmt:
> - 			set_ps_display(commandTag = "DROP");
> - 
>   			DropProceduralLanguage((DropPLangStmt *) parsetree);
>   			break;
>   
> --- 716,725 ----
> *************** ProcessUtility(Node *parsetree,
> *** 803,859 ****
>   			 *
>   			 */
>   		case T_CreateUserStmt:
> - 			set_ps_display(commandTag = "CREATE USER");
> - 
>   			CreateUser((CreateUserStmt *) parsetree);
>   			break;
>   
>   		case T_AlterUserStmt:
> - 			set_ps_display(commandTag = "ALTER USER");
> - 
>   			AlterUser((AlterUserStmt *) parsetree);
>   			break;
>   
>   		case T_DropUserStmt:
> - 			set_ps_display(commandTag = "DROP USER");
> - 
>   			DropUser((DropUserStmt *) parsetree);
>   			break;
>   
>   		case T_LockStmt:
> - 			set_ps_display(commandTag = "LOCK TABLE");
> - 
>   			LockTableCommand((LockStmt *) parsetree);
>   			break;
>   
>   		case T_ConstraintsSetStmt:
> - 			set_ps_display(commandTag = "SET CONSTRAINTS");
> - 
>   			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
>   			break;
>   
>   		case T_CreateGroupStmt:
> - 			set_ps_display(commandTag = "CREATE GROUP");
> - 
>   			CreateGroup((CreateGroupStmt *) parsetree);
>   			break;
>   
>   		case T_AlterGroupStmt:
> - 			set_ps_display(commandTag = "ALTER GROUP");
> - 
>   			AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
>   			break;
>   
>   		case T_DropGroupStmt:
> - 			set_ps_display(commandTag = "DROP GROUP");
> - 
>   			DropGroup((DropGroupStmt *) parsetree);
>   			break;
>   
>   		case T_CheckPointStmt:
>   			{
> - 				set_ps_display(commandTag = "CHECKPOINT");
> - 
>   				if (!superuser())
>   					elog(ERROR, "permission denied");
>   				CreateCheckPoint(false);
> --- 728,766 ----
> *************** ProcessUtility(Node *parsetree,
> *** 864,871 ****
>   			{
>   				ReindexStmt *stmt = (ReindexStmt *) parsetree;
>   
> - 				set_ps_display(commandTag = "REINDEX");
> - 
>   				switch (stmt->reindexType)
>   				{
>   					case INDEX:
> --- 771,776 ----
> *************** ProcessUtility(Node *parsetree,
> *** 913,919 ****
>   	}
>   
>   	/*
> ! 	 * tell fe/be or whatever that we're done.
>   	 */
> ! 	EndCommand(commandTag, dest);
>   }
> --- 818,826 ----
>   	}
>   
>   	/*
> ! 	 * Note: the "end-of-command" tag is to be sent by the caller,
> ! 	 * if appropriate.
>   	 */
> ! 	return;
>   }
> + 

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
> 
> http://www.postgresql.org/users-lounge/docs/faq.html

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman(at)candle(dot)pha(dot)pa(dot)us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

In response to

pgsql-patches by date

Next:From: Bruce MomjianDate: 2002-02-25 20:06:25
Subject: Re: PAM patch...
Previous:From: Bruce MomjianDate: 2002-02-25 18:10:43
Subject: Re: Patch to add CREATE OPERATOR CLASS

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group