diff options
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 69 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 31 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 20 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 13 |
4 files changed, 117 insertions, 16 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 7ed718f0b31..ae51505954f 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.215 2006/07/26 00:34:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.216 2006/08/02 01:59:45 joe Exp $ * *------------------------------------------------------------------------- */ @@ -59,6 +59,8 @@ static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path List *tlist, List *scan_clauses); static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses); +static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path, + List *tlist, List *scan_clauses); static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path, Plan *outer_plan, Plan *inner_plan); static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path, @@ -95,6 +97,8 @@ static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tidquals); static FunctionScan *make_functionscan(List *qptlist, List *qpqual, Index scanrelid); +static ValuesScan *make_valuesscan(List *qptlist, List *qpqual, + Index scanrelid); static BitmapAnd *make_bitmap_and(List *bitmapplans); static BitmapOr *make_bitmap_or(List *bitmapplans); static NestLoop *make_nestloop(List *tlist, @@ -146,6 +150,7 @@ create_plan(PlannerInfo *root, Path *best_path) case T_TidScan: case T_SubqueryScan: case T_FunctionScan: + case T_ValuesScan: plan = create_scan_plan(root, best_path); break; case T_HashJoin: @@ -262,6 +267,13 @@ create_scan_plan(PlannerInfo *root, Path *best_path) scan_clauses); break; + case T_ValuesScan: + plan = (Plan *) create_valuesscan_plan(root, + best_path, + tlist, + scan_clauses); + break; + default: elog(ERROR, "unrecognized node type: %d", (int) best_path->pathtype); @@ -315,12 +327,13 @@ use_physical_tlist(RelOptInfo *rel) int i; /* - * We can do this for real relation scans, subquery scans, and function - * scans (but not for, eg, joins). + * We can do this for real relation scans, subquery scans, function + * scans, and values scans (but not for, eg, joins). */ if (rel->rtekind != RTE_RELATION && rel->rtekind != RTE_SUBQUERY && - rel->rtekind != RTE_FUNCTION) + rel->rtekind != RTE_FUNCTION && + rel->rtekind != RTE_VALUES) return false; /* @@ -365,6 +378,7 @@ disuse_physical_tlist(Plan *plan, Path *path) case T_TidScan: case T_SubqueryScan: case T_FunctionScan: + case T_ValuesScan: plan->targetlist = build_relation_tlist(path->parent); break; default: @@ -1312,6 +1326,35 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path, return scan_plan; } +/* + * create_valuesscan_plan + * Returns a valuesscan plan for the base relation scanned by 'best_path' + * with restriction clauses 'scan_clauses' and targetlist 'tlist'. + */ +static ValuesScan * +create_valuesscan_plan(PlannerInfo *root, Path *best_path, + List *tlist, List *scan_clauses) +{ + ValuesScan *scan_plan; + Index scan_relid = best_path->parent->relid; + + /* it should be a values base rel... */ + Assert(scan_relid > 0); + Assert(best_path->parent->rtekind == RTE_VALUES); + + /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */ + scan_clauses = extract_actual_clauses(scan_clauses, false); + + /* Sort clauses into best execution order */ + scan_clauses = order_qual_clauses(root, scan_clauses); + + scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid); + + copy_path_costsize(&scan_plan->scan.plan, best_path); + + return scan_plan; +} + /***************************************************************************** * * JOIN METHODS @@ -2123,6 +2166,24 @@ make_functionscan(List *qptlist, return node; } +static ValuesScan * +make_valuesscan(List *qptlist, + List *qpqual, + Index scanrelid) +{ + ValuesScan *node = makeNode(ValuesScan); + Plan *plan = &node->scan.plan; + + /* cost should be inserted by caller */ + plan->targetlist = qptlist; + plan->qual = qpqual; + plan->lefttree = NULL; + plan->righttree = NULL; + node->scan.scanrelid = scanrelid; + + return node; +} + Append * make_append(List *appendplans, bool isTarget, List *tlist) { diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index c02f6e195cd..42ae15cd483 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.205 2006/07/26 19:31:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.206 2006/08/02 01:59:46 joe Exp $ * *------------------------------------------------------------------------- */ @@ -48,9 +48,10 @@ ParamListInfo PlannerBoundParamList = NULL; /* current boundParams */ #define EXPRKIND_QUAL 0 #define EXPRKIND_TARGET 1 #define EXPRKIND_RTFUNC 2 -#define EXPRKIND_LIMIT 3 -#define EXPRKIND_ININFO 4 -#define EXPRKIND_APPINFO 5 +#define EXPRKIND_VALUES 3 +#define EXPRKIND_LIMIT 4 +#define EXPRKIND_ININFO 5 +#define EXPRKIND_APPINFO 6 static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); @@ -295,7 +296,7 @@ subquery_planner(Query *parse, double tuple_fraction, preprocess_expression(root, (Node *) root->append_rel_list, EXPRKIND_APPINFO); - /* Also need to preprocess expressions for function RTEs */ + /* Also need to preprocess expressions for function and values RTEs */ foreach(l, parse->rtable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); @@ -303,6 +304,10 @@ subquery_planner(Query *parse, double tuple_fraction, if (rte->rtekind == RTE_FUNCTION) rte->funcexpr = preprocess_expression(root, rte->funcexpr, EXPRKIND_RTFUNC); + else if (rte->rtekind == RTE_VALUES) + rte->values_lists = (List *) + preprocess_expression(root, (Node *) rte->values_lists, + EXPRKIND_VALUES); } /* @@ -418,8 +423,10 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) * If the query has any join RTEs, replace join alias variables with * base-relation variables. We must do this before sublink processing, * else sublinks expanded out from join aliases wouldn't get processed. + * We can skip it in VALUES lists, however, since they can't contain + * any Vars at all. */ - if (root->hasJoinRTEs) + if (root->hasJoinRTEs && kind != EXPRKIND_VALUES) expr = flatten_join_alias_vars(root, expr); /* @@ -437,10 +444,14 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) * and we will waste cycles copying the tree. Notice however that we * still must do it for quals (to get AND/OR flatness); and if we are in a * subquery we should not assume it will be done only once. + * + * For VALUES lists we never do this at all, again on the grounds that + * we should optimize for one-time evaluation. */ - if (root->parse->jointree->fromlist != NIL || - kind == EXPRKIND_QUAL || - PlannerQueryLevel > 1) + if (kind != EXPRKIND_VALUES && + (root->parse->jointree->fromlist != NIL || + kind == EXPRKIND_QUAL || + PlannerQueryLevel > 1)) expr = eval_const_expressions(expr); /* @@ -465,7 +476,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) * SS_replace_correlation_vars ... */ - /* Replace uplevel vars with Param nodes */ + /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */ if (PlannerQueryLevel > 1) expr = SS_replace_correlation_vars(expr); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 2529c42ad95..11ef4765d86 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.122 2006/07/14 14:52:21 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.123 2006/08/02 01:59:46 joe Exp $ * *------------------------------------------------------------------------- */ @@ -186,6 +186,18 @@ set_plan_references(Plan *plan, List *rtable) fix_expr_references(plan, rte->funcexpr); } break; + case T_ValuesScan: + { + RangeTblEntry *rte; + + fix_expr_references(plan, (Node *) plan->targetlist); + fix_expr_references(plan, (Node *) plan->qual); + rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid, + rtable); + Assert(rte->rtekind == RTE_VALUES); + fix_expr_references(plan, (Node *) rte->values_lists); + } + break; case T_NestLoop: set_join_references((Join *) plan, rtable); fix_expr_references(plan, (Node *) plan->targetlist); @@ -522,6 +534,12 @@ adjust_plan_varnos(Plan *plan, int rtoffset) adjust_expr_varnos((Node *) plan->qual, rtoffset); /* rte was already fixed by set_subqueryscan_references */ break; + case T_ValuesScan: + ((ValuesScan *) plan)->scan.scanrelid += rtoffset; + adjust_expr_varnos((Node *) plan->targetlist, rtoffset); + adjust_expr_varnos((Node *) plan->qual, rtoffset); + /* rte was already fixed by set_subqueryscan_references */ + break; case T_NestLoop: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 0bc9a46c952..95e560478d9 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.110 2006/07/14 14:52:21 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.111 2006/08/02 01:59:46 joe Exp $ * *------------------------------------------------------------------------- */ @@ -1090,6 +1090,17 @@ finalize_plan(Plan *plan, List *rtable, } break; + case T_ValuesScan: + { + RangeTblEntry *rte; + + rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid, + rtable); + Assert(rte->rtekind == RTE_VALUES); + finalize_primnode((Node *) rte->values_lists, &context); + } + break; + case T_Append: { ListCell *l; |