Commit a36436ea authored by Tom Lane's avatar Tom Lane

Change fix_scan_expr() to avoid copying the input node tree in the common case

where rtoffset == 0.  In that case there is no need to change Var nodes,
and since filling in unset opfuncid fields is always safe, scribbling on the
input tree to that extent is not objectionable.  This brings the cost of this
operation back down to what it was in 8.2 for simple queries.  Per
investigation of performance gripe from Guillaume Smet.
parent 92c0bf09
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.139 2007/11/15 22:25:15 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.140 2007/11/24 00:39:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -73,6 +73,7 @@ static Plan *set_subqueryscan_references(PlannerGlobal *glob,
static bool trivial_subqueryscan(SubqueryScan *plan);
static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
indexed_tlist *outer_itlist);
......@@ -625,7 +626,23 @@ fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset)
context.glob = glob;
context.rtoffset = rtoffset;
return fix_scan_expr_mutator(node, &context);
if (rtoffset != 0)
{
return fix_scan_expr_mutator(node, &context);
}
else
{
/*
* If rtoffset == 0, we don't need to change any Vars, which makes
* it OK to just scribble on the input node tree instead of copying
* (since the only change, filling in any unset opfuncid fields,
* is harmless). This saves just enough cycles to be noticeable on
* trivial queries.
*/
(void) fix_scan_expr_walker(node, &context);
return node;
}
}
static Node *
......@@ -687,6 +704,34 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
(void *) context);
}
static bool
fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
{
if (node == NULL)
return false;
if (IsA(node, OpExpr))
set_opfuncid((OpExpr *) node);
else if (IsA(node, DistinctExpr))
set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
else if (IsA(node, NullIfExpr))
set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
else if (IsA(node, ScalarArrayOpExpr))
set_sa_opfuncid((ScalarArrayOpExpr *) node);
else if (IsA(node, Const))
{
Const *con = (Const *) node;
/* Check for regclass reference */
if (con->consttype == REGCLASSOID && !con->constisnull)
context->glob->relationOids =
lappend_oid(context->glob->relationOids,
DatumGetObjectId(con->constvalue));
return false;
}
return expression_tree_walker(node, fix_scan_expr_walker,
(void *) context);
}
/*
* set_join_references
* Modify the target list and quals of a join node to reference its
......
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