aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>1999-05-09 23:31:47 +0000
committerTom Lane <tgl@sss.pgh.pa.us>1999-05-09 23:31:47 +0000
commit0b69d8a27c1aedee7e56e6d5a14fe9a7e5c0cda8 (patch)
tree3acba1f6500ba489de2a52a386659403c439c32e /src
parent6458daa180586f9e49e67cfa4136094d139da950 (diff)
downloadpostgresql-0b69d8a27c1aedee7e56e6d5a14fe9a7e5c0cda8.tar.gz
postgresql-0b69d8a27c1aedee7e56e6d5a14fe9a7e5c0cda8.zip
Rearrange top-level rewrite operations so that EXPLAIN works
on queries involving UNION, EXCEPT, INTERSECT.
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/explain.c19
-rw-r--r--src/backend/rewrite/rewriteHandler.c63
-rw-r--r--src/backend/tcop/postgres.c143
3 files changed, 122 insertions, 103 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index a26579270c9..6a04417964b 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 1994-5, Regents of the University of California
*
- * $Id: explain.c,v 1.35 1999/04/25 03:19:09 tgl Exp $
+ * $Id: explain.c,v 1.36 1999/05/09 23:31:45 tgl Exp $
*
*/
#include <stdio.h>
@@ -49,15 +49,18 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
List *rewritten;
List *l;
+ /* rewriter and planner may not work in aborted state? */
if (IsAbortedTransactionBlockState())
{
- char *tag = "*ABORT STATE*";
-
- EndCommand(tag, dest);
-
elog(NOTICE, "(transaction aborted): %s",
"queries ignored until END");
+ return;
+ }
+ /* rewriter and planner will not cope with utility statements */
+ if (query->commandType == CMD_UTILITY)
+ {
+ elog(NOTICE, "Utility statements have no plan structure");
return;
}
@@ -67,7 +70,7 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
/* In the case of an INSTEAD NOTHING, tell at least that */
if (rewritten == NIL)
{
- elog(NOTICE, "query rewrites to nothing");
+ elog(NOTICE, "Query rewrites to nothing");
return;
}
@@ -88,7 +91,7 @@ ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
Plan *plan;
ExplainState *es;
- /* plan the queries (XXX we've ignored rewrite!!) */
+ /* plan the query */
plan = planner(query);
/* pg_plan could have failed */
@@ -195,7 +198,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
pname = "Hash";
break;
default:
- pname = "";
+ pname = "???";
break;
}
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index a9ff8a0a3b1..1ba1a5dd56e 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.37 1999/02/22 05:26:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.38 1999/05/09 23:31:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,8 +59,6 @@ static void modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_ind
static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);
static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);
static void modifyAggrefQual(Node **nodePtr, Query *parsetree);
-
-
static Query *fireRIRrules(Query *parsetree);
@@ -2634,12 +2632,12 @@ RewritePreprocessQuery(Query *parsetree)
/*
- * QueryRewrite -
+ * BasicQueryRewrite -
* rewrite one query via query rewrite system, possibly returning 0
* or many queries
*/
-List *
-QueryRewrite(Query *parsetree)
+static List *
+BasicQueryRewrite(Query *parsetree)
{
List *querylist;
List *results = NIL;
@@ -2672,10 +2670,57 @@ QueryRewrite(Query *parsetree)
}
return results;
}
-/***S*I***/
-/* This function takes two targetlists as arguments and checks if the targetlists are compatible
- * (i.e. both select for the same number of attributes and the types are compatible
+
+/*
+ * QueryRewrite -
+ * Primary entry point to the query rewriter.
+ * Rewrite one query via query rewrite system, possibly returning 0
+ * or many queries.
+ *
+ * NOTE: The code in QueryRewrite was formerly in pg_parse_and_plan(), and was
+ * moved here so that it would be invoked during EXPLAIN. The division of
+ * labor between this routine and BasicQueryRewrite is not obviously correct
+ * ... at least not to me ... tgl 5/99.
*/
+List *
+QueryRewrite(Query *parsetree)
+{
+ List *rewritten,
+ *rewritten_item;
+
+ /***S*I***/
+ /* Rewrite Union, Intersect and Except Queries
+ * to normal Union Queries using IN and NOT IN subselects */
+ if (parsetree->intersectClause)
+ parsetree = Except_Intersect_Rewrite(parsetree);
+
+ /* Rewrite basic queries (retrieve, append, delete, replace) */
+ rewritten = BasicQueryRewrite(parsetree);
+
+ /*
+ * Rewrite the UNIONS.
+ */
+ foreach (rewritten_item, rewritten)
+ {
+ Query *qry = (Query *) lfirst(rewritten_item);
+ List *union_result = NIL;
+ List *union_item;
+
+ foreach (union_item, qry->unionClause)
+ {
+ union_result = nconc(union_result,
+ BasicQueryRewrite((Query *) lfirst(union_item)));
+ }
+ qry->unionClause = union_result;
+ }
+
+ return rewritten;
+}
+
+/***S*I***/
+/* This function takes two targetlists as arguments and checks if the
+ * targetlists are compatible (i.e. both select for the same number of
+ * attributes and the types are compatible */
void check_targetlists_are_compatible(List *prev_target, List *current_target)
{
List *next_target;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index f196e51eaf0..24b2303ee9d 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.110 1999/05/03 19:09:54 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.111 1999/05/09 23:31:47 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -399,6 +399,49 @@ pg_parse_and_plan(char *query_string, /* string to execute */
List *rewritten = NIL;
Query *querytree;
+ if (DebugPrintQuery)
+ {
+ if (DebugPrintQuery > 3)
+ {
+ /* Print the query string as is if query debug level > 3 */
+ TPRINTF(TRACE_QUERY, "query: %s", query_string);
+ }
+ else
+ {
+ /* Print condensed query string to fit in one log line */
+ char buff[MAX_QUERY_SIZE + 1];
+ char c,
+ *s,
+ *d;
+ int n,
+ is_space = 1;
+
+ for (s = query_string, d = buff, n = 0; (c = *s) && (n < MAX_QUERY_SIZE); s++)
+ {
+ switch (c)
+ {
+ case '\r':
+ case '\n':
+ case '\t':
+ c = ' ';
+ /* fall through */
+ case ' ':
+ if (is_space)
+ continue;
+ is_space = 1;
+ break;
+ default:
+ is_space = 0;
+ break;
+ }
+ *d++ = c;
+ n++;
+ }
+ *d = '\0';
+ TPRINTF(TRACE_QUERY, "query: %s", buff);
+ }
+ }
+
/* ----------------
* (1) parse the request string into a list of parse trees
* ----------------
@@ -421,84 +464,30 @@ pg_parse_and_plan(char *query_string, /* string to execute */
/* ----------------
* (2) rewrite the queries, as necessary
+ *
+ * j counts queries output into new_list; the number of rewritten
+ * queries can be different from the original number.
* ----------------
*/
- j = 0; /* counter for the new_list, new_list can
- * be longer than old list as a result of
- * rewrites */
+ j = 0;
for (i = 0; i < querytree_list->len; i++)
{
- List *union_result,
- *union_list,
- *rewritten_list;
-
querytree = querytree_list->qtrees[i];
- /***S*I***/
- /* Rewrite Union, Intersect and Except Queries
- * to normal Union Queries using IN and NOT IN subselects */
- if(querytree->intersectClause != NIL)
- {
- querytree = Except_Intersect_Rewrite(querytree);
- }
-
- if (DebugPrintQuery)
+ if (DebugPrintParse)
{
- if (DebugPrintQuery > 3)
- {
- /* Print the query string as is if query debug level > 3 */
- TPRINTF(TRACE_QUERY, "query: %s", query_string);
- }
- else
- {
- /* Print condensed query string to fit in one log line */
- char buff[MAX_QUERY_SIZE + 1];
- char c,
- *s,
- *d;
- int n,
- is_space = 1;
-
- for (s = query_string, d = buff, n = 0; (c = *s) && (n < MAX_QUERY_SIZE); s++)
- {
- switch (c)
- {
- case '\r':
- case '\n':
- case '\t':
- c = ' ';
- /* fall through */
- case ' ':
- if (is_space)
- continue;
- is_space = 1;
- break;
- default:
- is_space = 0;
- break;
- }
- *d++ = c;
- n++;
- }
- *d = '\0';
- TPRINTF(TRACE_QUERY, "query: %s", buff);
- }
+ TPRINTF(TRACE_PARSE, "parser outputs:");
+ nodeDisplay(querytree);
}
- /* don't rewrite utilites */
+ /* don't rewrite utilites, just dump 'em into new_list */
if (querytree->commandType == CMD_UTILITY)
{
new_list->qtrees[j++] = querytree;
continue;
}
- if (DebugPrintParse)
- {
- TPRINTF(TRACE_PARSE, "parser outputs:");
- nodeDisplay(querytree);
- }
-
- /* rewrite queries (retrieve, append, delete, replace) */
+ /* rewrite regular queries */
rewritten = QueryRewrite(querytree);
if (rewritten != NIL)
@@ -506,19 +495,6 @@ pg_parse_and_plan(char *query_string, /* string to execute */
int len,
k;
- /*
- * Rewrite the UNIONS.
- */
- foreach(rewritten_list, rewritten)
- {
- Query *qry = (Query *) lfirst(rewritten_list);
-
- union_result = NIL;
- foreach(union_list, qry->unionClause)
- union_result = nconc(union_result, QueryRewrite((Query *) lfirst(union_list)));
- qry->unionClause = union_result;
- }
-
len = length(rewritten);
if (len == 1)
new_list->qtrees[j++] = (Query *) lfirst(rewritten);
@@ -530,19 +506,14 @@ pg_parse_and_plan(char *query_string, /* string to execute */
* we allocated one space
* for the query */
new_list->qtrees = realloc(new_list->qtrees,
- new_list->len * sizeof(Query *));
+ new_list->len * sizeof(Query *));
for (k = 0; k < len; k++)
new_list->qtrees[j++] = (Query *) nth(k, rewritten);
}
}
}
- /* ----------
- * Due to rewriting, the new list could also have been
- * shrunk (do instead nothing). Forget obsolete queries
- * at the end.
- * ----------
- */
+ /* Update new_list with correct final length */
new_list->len = j;
/* we're done with the original lists, free it */
@@ -657,7 +628,7 @@ pg_parse_and_plan(char *query_string, /* string to execute */
}
/* ----------
- * Check if the rewriting had thrown away anything
+ * Check if the rewriting had thrown away everything
* ----------
*/
if (querytree_list->len == 0)
@@ -1539,7 +1510,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.110 $ $Date: 1999/05/03 19:09:54 $\n");
+ puts("$Revision: 1.111 $ $Date: 1999/05/09 23:31:47 $\n");
}
/* ----------------