Re: Fix issuing of multiple command completions per command - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: Fix issuing of multiple command completions per command |
Date | |
Msg-id | 200202251834.g1PIYN926066@candle.pha.pa.us Whole thread Raw |
In response to | Fix issuing of multiple command completions per command (Fernando Nasser <fnasser@redhat.com>) |
List | 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@redhat.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@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
pgsql-patches by date: