From d508b057ac0834eb6ea83b10ba9fd6c439b454a4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 14 Oct 2002 22:14:35 +0000 Subject: Adjust handling of command status strings in the presence of rules, as per recent pghackers discussions. initdb forced due to change in fields of stored Query nodes. --- src/backend/nodes/copyfuncs.c | 4 +- src/backend/nodes/equalfuncs.c | 5 ++- src/backend/nodes/outfuncs.c | 7 +++- src/backend/nodes/readfuncs.c | 11 ++++-- src/backend/parser/analyze.c | 6 +-- src/backend/rewrite/rewriteHandler.c | 22 +++++++++-- src/backend/tcop/postgres.c | 71 +++++++++++++++++++++++++++++------- src/include/catalog/catversion.h | 4 +- src/include/nodes/parsenodes.h | 17 +++++++-- 9 files changed, 113 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index bce849e4ec5..5fff2f762ab 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.213 2002/09/22 19:42:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.214 2002/10/14 22:14:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1778,6 +1778,7 @@ _copyQuery(Query *from) Query *newnode = makeNode(Query); newnode->commandType = from->commandType; + newnode->querySource = from->querySource; Node_Copy(from, newnode, utilityStmt); newnode->resultRelation = from->resultRelation; Node_Copy(from, newnode, into); @@ -1785,7 +1786,6 @@ _copyQuery(Query *from) newnode->isBinary = from->isBinary; newnode->hasAggs = from->hasAggs; newnode->hasSubLinks = from->hasSubLinks; - newnode->originalQuery = from->originalQuery; Node_Copy(from, newnode, rtable); Node_Copy(from, newnode, jointree); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 82d4fc6ab63..551c32d5dba 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.160 2002/09/22 19:42:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.161 2002/10/14 22:14:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -573,6 +573,8 @@ _equalQuery(Query *a, Query *b) { if (a->commandType != b->commandType) return false; + if (a->querySource != b->querySource) + return false; if (!equal(a->utilityStmt, b->utilityStmt)) return false; if (a->resultRelation != b->resultRelation) @@ -587,7 +589,6 @@ _equalQuery(Query *a, Query *b) return false; if (a->hasSubLinks != b->hasSubLinks) return false; - /* we deliberately ignore originalQuery */ if (!equal(a->rtable, b->rtable)) return false; if (!equal(a->jointree, b->jointree)) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 364aa774ada..e1a34118a62 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.175 2002/09/22 19:42:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.176 2002/10/14 22:14:34 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -229,7 +229,8 @@ _outIndexElem(StringInfo str, IndexElem *node) static void _outQuery(StringInfo str, Query *node) { - appendStringInfo(str, " QUERY :command %d :utility ", node->commandType); + appendStringInfo(str, " QUERY :command %d :source %d :utility ", + (int) node->commandType, (int) node->querySource); /* * Hack to work around missing outfuncs routines for a lot of the @@ -299,6 +300,8 @@ _outQuery(StringInfo str, Query *node) appendStringInfo(str, " :resultRelations "); _outIntList(str, node->resultRelations); + + /* planner-internal fields are not written out */ } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index fc4bb97e4a7..33e28413439 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.134 2002/09/22 19:42:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.135 2002/10/14 22:14:34 tgl Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -123,6 +123,10 @@ _readQuery(void) token = pg_strtok(&length); /* get commandType */ local_node->commandType = atoi(token); + token = pg_strtok(&length); /* skip :source */ + token = pg_strtok(&length); /* get querySource */ + local_node->querySource = atoi(token); + token = pg_strtok(&length); /* skip :utility */ local_node->utilityStmt = nodeRead(true); @@ -149,9 +153,6 @@ _readQuery(void) token = pg_strtok(&length); /* get hasSubLinks */ local_node->hasSubLinks = strtobool(token); - /* we always want originalQuery to be false in a read-in query */ - local_node->originalQuery = false; - token = pg_strtok(&length); /* skip :rtable */ local_node->rtable = nodeRead(true); @@ -188,6 +189,8 @@ _readQuery(void) token = pg_strtok(&length); /* skip :resultRelations */ local_node->resultRelations = toIntList(nodeRead(true)); + /* planner-internal fields are left zero */ + return local_node; } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index fe058125a04..2dcaadc177f 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.250 2002/09/22 00:37:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.251 2002/10/14 22:14:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -164,13 +164,13 @@ parse_analyze(Node *parseTree, ParseState *parentParseState) /* * Make sure that only the original query is marked original. We have * to do this explicitly since recursive calls of parse_analyze will - * have set originalQuery in some of the added-on queries. + * have marked some of the added-on queries as "original". */ foreach(listscan, result) { Query *q = lfirst(listscan); - q->originalQuery = (q == query); + q->querySource = (q == query ? QSRC_ORIGINAL : QSRC_PARSER); } pfree(pstate); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 0b2d839eb3f..180e56d9208 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.110 2002/09/18 21:35:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.111 2002/10/14 22:14:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -942,6 +942,7 @@ fireRules(Query *parsetree, RewriteRule *rule_lock = (RewriteRule *) lfirst(i); Node *event_qual; List *actions; + QuerySource qsrc; List *r; /* multiple rule action time */ @@ -949,7 +950,18 @@ fireRules(Query *parsetree, event_qual = rule_lock->qual; actions = rule_lock->actions; - if (event_qual != NULL && *instead_flag) + /* Determine correct QuerySource value for actions */ + if (rule_lock->isInstead) + { + if (event_qual != NULL) + qsrc = QSRC_QUAL_INSTEAD_RULE; + else + qsrc = QSRC_INSTEAD_RULE; + } + else + qsrc = QSRC_NON_INSTEAD_RULE; + + if (qsrc == QSRC_QUAL_INSTEAD_RULE) { Query *qual_product; @@ -976,6 +988,7 @@ fireRules(Query *parsetree, *qual_products = makeList1(qual_product); } + /* Now process the rule's actions and add them to the result list */ foreach(r, actions) { Query *rule_action = lfirst(r); @@ -986,6 +999,8 @@ fireRules(Query *parsetree, rule_action = rewriteRuleAction(parsetree, rule_action, event_qual, rt_index, event); + rule_action->querySource = qsrc; + results = lappend(results, rule_action); } @@ -993,9 +1008,10 @@ fireRules(Query *parsetree, * If this was an unqualified instead rule, throw away an * eventually saved 'default' parsetree */ - if (event_qual == NULL && *instead_flag) + if (qsrc == QSRC_INSTEAD_RULE) *qual_products = NIL; } + return results; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 1b636c18d73..9538b34a4e9 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.301 2002/10/13 16:55:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.302 2002/10/14 22:14:35 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -621,6 +621,8 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ Node *parsetree = (Node *) lfirst(parsetree_item); const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; + CmdType origCmdType; + bool foundOriginalQuery = false; List *querytree_list, *querytree_item; @@ -632,6 +634,26 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ */ commandTag = CreateCommandTag(parsetree); + switch (nodeTag(parsetree)) + { + case T_InsertStmt: + origCmdType = CMD_INSERT; + break; + case T_DeleteStmt: + origCmdType = CMD_DELETE; + break; + case T_UpdateStmt: + origCmdType = CMD_UPDATE; + break; + case T_SelectStmt: + origCmdType = CMD_SELECT; + break; + default: + /* Otherwise, never match commandType */ + origCmdType = CMD_UNKNOWN; + break; + } + set_ps_display(commandTag); BeginCommand(commandTag, dest); @@ -694,6 +716,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ { Query *querytree = (Query *) lfirst(querytree_item); bool endTransactionBlock = false; + bool canSetTag; /* Make sure we are in a transaction command */ if (!xact_started) @@ -708,6 +731,24 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ */ CHECK_FOR_INTERRUPTS(); + /* + * This query can set the completion tag if it is the original + * query, or if it is an INSTEAD query of the same kind as the + * original and we haven't yet seen the original query. + */ + if (querytree->querySource == QSRC_ORIGINAL) + { + canSetTag = true; + foundOriginalQuery = true; + } + else if (!foundOriginalQuery && + querytree->commandType == origCmdType && + (querytree->querySource == QSRC_INSTEAD_RULE || + querytree->querySource == QSRC_QUAL_INSTEAD_RULE)) + canSetTag = true; + else + canSetTag = false; + if (querytree->commandType == CMD_UTILITY) { /* @@ -736,7 +777,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ IsA(utilityStmt, VariableResetStmt)) endTransactionBlock = true; - if (querytree->originalQuery) + if (canSetTag) { /* utility statement can override default tag string */ ProcessUtility(utilityStmt, dest, completionTag); @@ -785,9 +826,9 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ { elog(DEBUG2, "ProcessQuery"); - if (querytree->originalQuery || length(querytree_list) == 1) + if (canSetTag) { - /* original stmt can override default tag string */ + /* statement can override default tag string */ ProcessQuery(querytree, plan, dest, completionTag); commandTag = completionTag; } @@ -853,17 +894,21 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */ /* * It is possible that the original query was removed due to a DO - * INSTEAD rewrite rule. In that case we will still have the - * default completion tag, which is fine for most purposes, but it + * INSTEAD rewrite rule. If so, and if we found no INSTEAD query + * matching the command type, we will still have the default + * completion tag. This is fine for most purposes, but it * may confuse clients if it's INSERT/UPDATE/DELETE. Clients * expect those tags to have counts after them (cf. ProcessQuery). */ - if (strcmp(commandTag, "INSERT") == 0) - commandTag = "INSERT 0 0"; - else if (strcmp(commandTag, "UPDATE") == 0) - commandTag = "UPDATE 0"; - else if (strcmp(commandTag, "DELETE") == 0) - commandTag = "DELETE 0"; + if (!foundOriginalQuery) + { + if (strcmp(commandTag, "INSERT") == 0) + commandTag = "INSERT 0 0"; + else if (strcmp(commandTag, "UPDATE") == 0) + commandTag = "UPDATE 0"; + else if (strcmp(commandTag, "DELETE") == 0) + commandTag = "DELETE 0"; + } /* * Tell client that we're done with this query. Note we emit @@ -1724,7 +1769,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.301 $ $Date: 2002/10/13 16:55:05 $\n"); + puts("$Revision: 1.302 $ $Date: 2002/10/14 22:14:35 $\n"); } /* diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 431e317c89b..967cb794f7d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.160 2002/09/22 19:42:51 tgl Exp $ + * $Id: catversion.h,v 1.161 2002/10/14 22:14:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200209221 +#define CATALOG_VERSION_NO 200210141 #endif diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index cde4acebc21..ee0d2210134 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.208 2002/09/22 19:42:52 tgl Exp $ + * $Id: parsenodes.h,v 1.209 2002/10/14 22:14:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,17 @@ #include "nodes/primnodes.h" +/* Possible sources of a Query */ +typedef enum QuerySource +{ + QSRC_ORIGINAL, /* original parsetree (explicit query) */ + QSRC_PARSER, /* added by parse analysis */ + QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */ + QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */ + QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */ +} QuerySource; + + /***************************************************************************** * Query Tree *****************************************************************************/ @@ -37,6 +48,8 @@ typedef struct Query CmdType commandType; /* select|insert|update|delete|utility */ + QuerySource querySource; /* where did I come from? */ + Node *utilityStmt; /* non-null if this is a non-optimizable * statement */ @@ -49,8 +62,6 @@ typedef struct Query bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasSubLinks; /* has subquery SubLink */ - bool originalQuery; /* marks original query through rewriting */ - List *rtable; /* list of range table entries */ FromExpr *jointree; /* table join tree (FROM and WHERE * clauses) */ -- cgit v1.2.3