|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.139 2007/11/15 22:25:15 momjian Exp $ |
| 12 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.140 2007/11/24 00:39:44 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -73,6 +73,7 @@ static Plan *set_subqueryscan_references(PlannerGlobal *glob,
|
73 | 73 | staticbooltrivial_subqueryscan(SubqueryScan*plan);
|
74 | 74 | staticNode*fix_scan_expr(PlannerGlobal*glob,Node*node,intrtoffset);
|
75 | 75 | staticNode*fix_scan_expr_mutator(Node*node,fix_scan_expr_context*context);
|
| 76 | +staticboolfix_scan_expr_walker(Node*node,fix_scan_expr_context*context); |
76 | 77 | staticvoidset_join_references(PlannerGlobal*glob,Join*join,intrtoffset);
|
77 | 78 | staticvoidset_inner_join_references(PlannerGlobal*glob,Plan*inner_plan,
|
78 | 79 | indexed_tlist*outer_itlist);
|
@@ -625,7 +626,23 @@ fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset)
|
625 | 626 |
|
626 | 627 | context.glob=glob;
|
627 | 628 | context.rtoffset=rtoffset;
|
628 |
| -returnfix_scan_expr_mutator(node,&context); |
| 629 | + |
| 630 | +if (rtoffset!=0) |
| 631 | +{ |
| 632 | +returnfix_scan_expr_mutator(node,&context); |
| 633 | +} |
| 634 | +else |
| 635 | +{ |
| 636 | +/* |
| 637 | + * If rtoffset == 0, we don't need to change any Vars, which makes |
| 638 | + * it OK to just scribble on the input node tree instead of copying |
| 639 | + * (since the only change, filling in any unset opfuncid fields, |
| 640 | + * is harmless). This saves just enough cycles to be noticeable on |
| 641 | + * trivial queries. |
| 642 | + */ |
| 643 | +(void)fix_scan_expr_walker(node,&context); |
| 644 | +returnnode; |
| 645 | +} |
629 | 646 | }
|
630 | 647 |
|
631 | 648 | staticNode*
|
@@ -687,6 +704,34 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
|
687 | 704 | (void*)context);
|
688 | 705 | }
|
689 | 706 |
|
| 707 | +staticbool |
| 708 | +fix_scan_expr_walker(Node*node,fix_scan_expr_context*context) |
| 709 | +{ |
| 710 | +if (node==NULL) |
| 711 | +return false; |
| 712 | +if (IsA(node,OpExpr)) |
| 713 | +set_opfuncid((OpExpr*)node); |
| 714 | +elseif (IsA(node,DistinctExpr)) |
| 715 | +set_opfuncid((OpExpr*)node);/* rely on struct equivalence */ |
| 716 | +elseif (IsA(node,NullIfExpr)) |
| 717 | +set_opfuncid((OpExpr*)node);/* rely on struct equivalence */ |
| 718 | +elseif (IsA(node,ScalarArrayOpExpr)) |
| 719 | +set_sa_opfuncid((ScalarArrayOpExpr*)node); |
| 720 | +elseif (IsA(node,Const)) |
| 721 | +{ |
| 722 | +Const*con= (Const*)node; |
| 723 | + |
| 724 | +/* Check for regclass reference */ |
| 725 | +if (con->consttype==REGCLASSOID&& !con->constisnull) |
| 726 | +context->glob->relationOids= |
| 727 | +lappend_oid(context->glob->relationOids, |
| 728 | +DatumGetObjectId(con->constvalue)); |
| 729 | +return false; |
| 730 | +} |
| 731 | +returnexpression_tree_walker(node,fix_scan_expr_walker, |
| 732 | + (void*)context); |
| 733 | +} |
| 734 | + |
690 | 735 | /*
|
691 | 736 | * set_join_references
|
692 | 737 | * Modify the target list and quals of a join node to reference its
|
|