Commit 742fd06d authored by Tom Lane's avatar Tom Lane

Fix up ruleutils.c for CTE features. The main problem was that

get_name_for_var_field didn't have enough context to interpret a reference to
a CTE query's output.  Fixing this requires separate hacks for the regular
deparse case (pg_get_ruledef) and for the EXPLAIN case, since the available
context information is quite different.  It's pretty nearly parallel to the
existing code for SUBQUERY RTEs, though.  Also, add code to make sure we
qualify a relation name that matches a CTE name; else the CTE will mistakenly
capture the reference when reloading the rule.

In passing, fix a pre-existing problem with get_name_for_var_field not working
on variables in targetlists of SubqueryScan plan nodes.  Although latent all
along, this wasn't a problem until we made EXPLAIN VERBOSE try to print
targetlists.  To do this, refactor the deparse_context_for_plan API so that
the special case for SubqueryScan is all on ruleutils.c's side.
parent bf461538
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.179 2008/10/04 21:56:52 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.180 2008/10/06 20:29:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -63,7 +63,7 @@ static void explain_outNode(StringInfo str, ...@@ -63,7 +63,7 @@ static void explain_outNode(StringInfo str,
static void show_plan_tlist(Plan *plan, static void show_plan_tlist(Plan *plan,
StringInfo str, int indent, ExplainState *es); StringInfo str, int indent, ExplainState *es);
static void show_scan_qual(List *qual, const char *qlabel, static void show_scan_qual(List *qual, const char *qlabel,
int scanrelid, Plan *outer_plan, Plan *inner_plan, int scanrelid, Plan *scan_plan, Plan *outer_plan,
StringInfo str, int indent, ExplainState *es); StringInfo str, int indent, ExplainState *es);
static void show_upper_qual(List *qual, const char *qlabel, Plan *plan, static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
StringInfo str, int indent, ExplainState *es); StringInfo str, int indent, ExplainState *es);
...@@ -804,19 +804,19 @@ explain_outNode(StringInfo str, ...@@ -804,19 +804,19 @@ explain_outNode(StringInfo str,
show_scan_qual(((IndexScan *) plan)->indexqualorig, show_scan_qual(((IndexScan *) plan)->indexqualorig,
"Index Cond", "Index Cond",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
show_scan_qual(plan->qual, show_scan_qual(plan->qual,
"Filter", "Filter",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
break; break;
case T_BitmapIndexScan: case T_BitmapIndexScan:
show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig, show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
"Index Cond", "Index Cond",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
break; break;
case T_BitmapHeapScan: case T_BitmapHeapScan:
...@@ -824,7 +824,7 @@ explain_outNode(StringInfo str, ...@@ -824,7 +824,7 @@ explain_outNode(StringInfo str,
show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig, show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig,
"Recheck Cond", "Recheck Cond",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
/* FALL THRU */ /* FALL THRU */
case T_SeqScan: case T_SeqScan:
...@@ -835,15 +835,14 @@ explain_outNode(StringInfo str, ...@@ -835,15 +835,14 @@ explain_outNode(StringInfo str,
show_scan_qual(plan->qual, show_scan_qual(plan->qual,
"Filter", "Filter",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
break; break;
case T_SubqueryScan: case T_SubqueryScan:
show_scan_qual(plan->qual, show_scan_qual(plan->qual,
"Filter", "Filter",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, plan, outer_plan,
((SubqueryScan *) plan)->subplan,
str, indent, es); str, indent, es);
break; break;
case T_TidScan: case T_TidScan:
...@@ -859,12 +858,12 @@ explain_outNode(StringInfo str, ...@@ -859,12 +858,12 @@ explain_outNode(StringInfo str,
show_scan_qual(tidquals, show_scan_qual(tidquals,
"TID Cond", "TID Cond",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
show_scan_qual(plan->qual, show_scan_qual(plan->qual,
"Filter", "Filter",
((Scan *) plan)->scanrelid, ((Scan *) plan)->scanrelid,
outer_plan, NULL, plan, outer_plan,
str, indent, es); str, indent, es);
} }
break; break;
...@@ -1121,9 +1120,10 @@ show_plan_tlist(Plan *plan, ...@@ -1121,9 +1120,10 @@ show_plan_tlist(Plan *plan,
return; return;
/* Set up deparsing context */ /* Set up deparsing context */
context = deparse_context_for_plan((Node *) outerPlan(plan), context = deparse_context_for_plan((Node *) plan,
(Node *) innerPlan(plan), NULL,
es->rtable); es->rtable,
es->pstmt->subplans);
useprefix = list_length(es->rtable) > 1; useprefix = list_length(es->rtable) > 1;
/* Emit line prefix */ /* Emit line prefix */
...@@ -1153,12 +1153,11 @@ show_plan_tlist(Plan *plan, ...@@ -1153,12 +1153,11 @@ show_plan_tlist(Plan *plan,
* Show a qualifier expression for a scan plan node * Show a qualifier expression for a scan plan node
* *
* Note: outer_plan is the referent for any OUTER vars in the scan qual; * Note: outer_plan is the referent for any OUTER vars in the scan qual;
* this would be the outer side of a nestloop plan. inner_plan should be * this would be the outer side of a nestloop plan. Pass NULL if none.
* NULL except for a SubqueryScan plan node, where it should be the subplan.
*/ */
static void static void
show_scan_qual(List *qual, const char *qlabel, show_scan_qual(List *qual, const char *qlabel,
int scanrelid, Plan *outer_plan, Plan *inner_plan, int scanrelid, Plan *scan_plan, Plan *outer_plan,
StringInfo str, int indent, ExplainState *es) StringInfo str, int indent, ExplainState *es)
{ {
List *context; List *context;
...@@ -1175,10 +1174,11 @@ show_scan_qual(List *qual, const char *qlabel, ...@@ -1175,10 +1174,11 @@ show_scan_qual(List *qual, const char *qlabel,
node = (Node *) make_ands_explicit(qual); node = (Node *) make_ands_explicit(qual);
/* Set up deparsing context */ /* Set up deparsing context */
context = deparse_context_for_plan((Node *) outer_plan, context = deparse_context_for_plan((Node *) scan_plan,
(Node *) inner_plan, (Node *) outer_plan,
es->rtable); es->rtable,
useprefix = (outer_plan != NULL || inner_plan != NULL); es->pstmt->subplans);
useprefix = (outer_plan != NULL || IsA(scan_plan, SubqueryScan));
/* Deparse the expression */ /* Deparse the expression */
exprstr = deparse_expression(node, context, useprefix, false); exprstr = deparse_expression(node, context, useprefix, false);
...@@ -1207,9 +1207,10 @@ show_upper_qual(List *qual, const char *qlabel, Plan *plan, ...@@ -1207,9 +1207,10 @@ show_upper_qual(List *qual, const char *qlabel, Plan *plan,
return; return;
/* Set up deparsing context */ /* Set up deparsing context */
context = deparse_context_for_plan((Node *) outerPlan(plan), context = deparse_context_for_plan((Node *) plan,
(Node *) innerPlan(plan), NULL,
es->rtable); es->rtable,
es->pstmt->subplans);
useprefix = list_length(es->rtable) > 1; useprefix = list_length(es->rtable) > 1;
/* Deparse the expression */ /* Deparse the expression */
...@@ -1244,9 +1245,10 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols, ...@@ -1244,9 +1245,10 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
appendStringInfo(str, " %s: ", qlabel); appendStringInfo(str, " %s: ", qlabel);
/* Set up deparsing context */ /* Set up deparsing context */
context = deparse_context_for_plan((Node *) outerPlan(sortplan), context = deparse_context_for_plan((Node *) sortplan,
NULL, /* Sort has no innerPlan */ NULL,
es->rtable); es->rtable,
es->pstmt->subplans);
useprefix = list_length(es->rtable) > 1; useprefix = list_length(es->rtable) > 1;
for (keyno = 0; keyno < nkeys; keyno++) for (keyno = 0; keyno < nkeys; keyno++)
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.322 2008/10/05 17:33:17 petere Exp $ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.323 2008/10/06 20:29:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -549,8 +549,8 @@ extern Datum pg_get_function_result(PG_FUNCTION_ARGS); ...@@ -549,8 +549,8 @@ extern Datum pg_get_function_result(PG_FUNCTION_ARGS);
extern char *deparse_expression(Node *expr, List *dpcontext, extern char *deparse_expression(Node *expr, List *dpcontext,
bool forceprefix, bool showimplicit); bool forceprefix, bool showimplicit);
extern List *deparse_context_for(const char *aliasname, Oid relid); extern List *deparse_context_for(const char *aliasname, Oid relid);
extern List *deparse_context_for_plan(Node *outer_plan, Node *inner_plan, extern List *deparse_context_for_plan(Node *plan, Node *outer_plan,
List *rtable); List *rtable, List *subplans);
extern const char *quote_identifier(const char *ident); extern const char *quote_identifier(const char *ident);
extern char *quote_qualified_identifier(const char *namespace, extern char *quote_qualified_identifier(const char *namespace,
const char *ident); const char *ident);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment