diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 9a84509f74..cbc01bae8c 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,5 +1,5 @@ @@ -319,7 +319,7 @@ amrestrpos (IndexScanDesc scan); void -amcostestimate (Query *root, +amcostestimate (PlannerInfo *root, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, @@ -656,7 +656,7 @@ amcostestimate (Query *root, void -amcostestimate (Query *root, +amcostestimate (PlannerInfo *root, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, @@ -672,7 +672,7 @@ amcostestimate (Query *root, root - The query being processed. + The planner's information about the query being processed. diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 2d5dd7b2b5..2f7642276c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.304 2005/04/28 21:47:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.305 2005/06/05 22:32:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1615,18 +1615,6 @@ _copyQuery(Query *from) COPY_NODE_FIELD(limitCount); COPY_NODE_FIELD(setOperations); COPY_NODE_FIELD(resultRelations); - COPY_NODE_FIELD(in_info_list); - COPY_SCALAR_FIELD(hasJoinRTEs); - COPY_SCALAR_FIELD(hasHavingQual); - - /* - * We do not copy the other planner internal fields: base_rel_list, - * other_rel_list, join_rel_list, equi_key_list, query_pathkeys. That - * would get us into copying RelOptInfo/Path trees, which we don't - * want to do. It is necessary to copy in_info_list, hasJoinRTEs, - * and hasHavingQual for the benefit of inheritance_planner(), which - * may try to copy a Query in which these are already set. - */ return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a9570201be..a1d951112c 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.241 2005/04/28 21:47:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.242 2005/06/05 22:32:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -653,10 +653,6 @@ _equalQuery(Query *a, Query *b) COMPARE_NODE_FIELD(setOperations); COMPARE_NODE_FIELD(resultRelations); - /* - * We do not check the planner-internal fields. They might not be set - * yet, and in any case they should be derivable from the other fields. - */ return true; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 37918e8658..51a85a90b3 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.252 2005/05/09 15:09:19 ishii Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.253 2005/06/05 22:32:54 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1145,6 +1145,69 @@ _outHashPath(StringInfo str, HashPath *node) WRITE_NODE_FIELD(path_hashclauses); } +static void +_outPlannerInfo(StringInfo str, PlannerInfo *node) +{ + WRITE_NODE_TYPE("PLANNERINFO"); + + WRITE_NODE_FIELD(parse); + WRITE_NODE_FIELD(base_rel_list); + WRITE_NODE_FIELD(other_rel_list); + WRITE_NODE_FIELD(join_rel_list); + WRITE_NODE_FIELD(equi_key_list); + WRITE_NODE_FIELD(in_info_list); + WRITE_NODE_FIELD(query_pathkeys); + WRITE_BOOL_FIELD(hasJoinRTEs); + WRITE_BOOL_FIELD(hasHavingQual); +} + +static void +_outRelOptInfo(StringInfo str, RelOptInfo *node) +{ + WRITE_NODE_TYPE("RELOPTINFO"); + + /* NB: this isn't a complete set of fields */ + WRITE_ENUM_FIELD(reloptkind, RelOptKind); + WRITE_BITMAPSET_FIELD(relids); + WRITE_FLOAT_FIELD(rows, "%.0f"); + WRITE_INT_FIELD(width); + WRITE_NODE_FIELD(reltargetlist); + WRITE_NODE_FIELD(pathlist); + WRITE_NODE_FIELD(cheapest_startup_path); + WRITE_NODE_FIELD(cheapest_total_path); + WRITE_NODE_FIELD(cheapest_unique_path); + WRITE_UINT_FIELD(relid); + WRITE_ENUM_FIELD(rtekind, RTEKind); + WRITE_UINT_FIELD(min_attr); + WRITE_UINT_FIELD(max_attr); + WRITE_NODE_FIELD(indexlist); + WRITE_UINT_FIELD(pages); + WRITE_FLOAT_FIELD(tuples, "%.0f"); + WRITE_NODE_FIELD(subplan); + WRITE_NODE_FIELD(baserestrictinfo); + WRITE_BITMAPSET_FIELD(outerjoinset); + WRITE_NODE_FIELD(joininfo); + WRITE_BITMAPSET_FIELD(index_outer_relids); + WRITE_NODE_FIELD(index_inner_paths); +} + +static void +_outIndexOptInfo(StringInfo str, IndexOptInfo *node) +{ + WRITE_NODE_TYPE("INDEXOPTINFO"); + + /* NB: this isn't a complete set of fields */ + WRITE_OID_FIELD(indexoid); + /* Do NOT print rel field, else infinite recursion */ + WRITE_UINT_FIELD(pages); + WRITE_FLOAT_FIELD(tuples, "%.0f"); + WRITE_INT_FIELD(ncolumns); + WRITE_NODE_FIELD(indexprs); + WRITE_NODE_FIELD(indpred); + WRITE_BOOL_FIELD(predOK); + WRITE_BOOL_FIELD(unique); +} + static void _outPathKeyItem(StringInfo str, PathKeyItem *node) { @@ -1185,6 +1248,15 @@ _outJoinInfo(StringInfo str, JoinInfo *node) WRITE_NODE_FIELD(jinfo_restrictinfo); } +static void +_outInnerIndexscanInfo(StringInfo str, InnerIndexscanInfo *node) +{ + WRITE_NODE_TYPE("INNERINDEXSCANINFO"); + WRITE_BITMAPSET_FIELD(other_relids); + WRITE_BOOL_FIELD(isouterjoin); + WRITE_NODE_FIELD(best_innerpath); +} + static void _outInClauseInfo(StringInfo str, InClauseInfo *node) { @@ -1395,8 +1467,6 @@ _outQuery(StringInfo str, Query *node) WRITE_NODE_FIELD(limitCount); WRITE_NODE_FIELD(setOperations); WRITE_NODE_FIELD(resultRelations); - - /* planner-internal fields are not written out */ } static void @@ -1905,6 +1975,15 @@ _outNode(StringInfo str, void *obj) case T_HashPath: _outHashPath(str, obj); break; + case T_PlannerInfo: + _outPlannerInfo(str, obj); + break; + case T_RelOptInfo: + _outRelOptInfo(str, obj); + break; + case T_IndexOptInfo: + _outIndexOptInfo(str, obj); + break; case T_PathKeyItem: _outPathKeyItem(str, obj); break; @@ -1914,6 +1993,9 @@ _outNode(StringInfo str, void *obj) case T_JoinInfo: _outJoinInfo(str, obj); break; + case T_InnerIndexscanInfo: + _outInnerIndexscanInfo(str, obj); + break; case T_InClauseInfo: _outInClauseInfo(str, obj); break; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index ef405f7a02..e01646a71d 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.177 2005/04/28 21:47:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.178 2005/06/05 22:32:54 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -156,8 +156,6 @@ _readQuery(void) READ_NODE_FIELD(setOperations); READ_NODE_FIELD(resultRelations); - /* planner-internal fields are left zero */ - READ_DONE(); } diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README index 174ad4fd0a..3c2fd32d52 100644 --- a/src/backend/optimizer/README +++ b/src/backend/optimizer/README @@ -245,6 +245,8 @@ planner() Optimizer Data Structures ------------------------- +PlannerInfo - global information for planning a particular Query + RelOptInfo - a relation or joined relations RestrictInfo - WHERE clauses, like "x = 3" or "y = z" diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 08d80f80b7..3460eb5b8e 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.73 2004/12/31 21:59:58 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.74 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ #include "utils/memutils.h" -static bool desirable_join(Query *root, +static bool desirable_join(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel); @@ -241,7 +241,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) * Heuristics for gimme_tree: do we want to join these two relations? */ static bool -desirable_join(Query *root, +desirable_join(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel) { ListCell *l; diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index f827e865bf..f19f5f7c34 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.48 2004/12/31 21:59:58 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.49 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -63,7 +63,7 @@ static int gimme_number_generations(int pool_size); */ RelOptInfo * -geqo(Query *root, int number_of_rels, List *initial_rels) +geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) { GeqoEvalData evaldata; int generation; diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 7e7666015a..e41701d044 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.130 2005/06/04 19:19:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.131 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,17 +38,17 @@ bool enable_geqo = false; /* just in case GUC doesn't set it */ int geqo_threshold; -static void set_base_rel_pathlists(Query *root); -static void set_plain_rel_pathlist(Query *root, RelOptInfo *rel, +static void set_base_rel_pathlists(PlannerInfo *root); +static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); -static void set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, +static void set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte, List *inheritlist); -static void set_subquery_pathlist(Query *root, RelOptInfo *rel, +static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); -static void set_function_pathlist(Query *root, RelOptInfo *rel, +static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); -static RelOptInfo *make_one_rel_by_joins(Query *root, int levels_needed, +static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed, List *initial_rels); static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery, bool *differentTypes); @@ -70,7 +70,7 @@ static void recurse_push_qual(Node *setOp, Query *topquery, * single rel that represents the join of all base rels in the query. */ RelOptInfo * -make_one_rel(Query *root) +make_one_rel(PlannerInfo *root) { RelOptInfo *rel; @@ -82,9 +82,10 @@ make_one_rel(Query *root) /* * Generate access paths for the entire join tree. */ - Assert(root->jointree != NULL && IsA(root->jointree, FromExpr)); + Assert(root->parse->jointree != NULL && + IsA(root->parse->jointree, FromExpr)); - rel = make_fromexpr_rel(root, root->jointree); + rel = make_fromexpr_rel(root, root->parse->jointree); /* * The result should join all the query's base rels. @@ -101,7 +102,7 @@ make_one_rel(Query *root) * Each useful path is attached to its relation's 'pathlist' field. */ static void -set_base_rel_pathlists(Query *root) +set_base_rel_pathlists(PlannerInfo *root) { ListCell *l; @@ -113,7 +114,7 @@ set_base_rel_pathlists(Query *root) List *inheritlist; Assert(rti > 0); /* better be base rel */ - rte = rt_fetch(rti, root->rtable); + rte = rt_fetch(rti, root->parse->rtable); if (rel->rtekind == RTE_SUBQUERY) { @@ -147,7 +148,7 @@ set_base_rel_pathlists(Query *root) * Build access paths for a plain relation (no subquery, no inheritance) */ static void -set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) +set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) { /* Mark rel with estimated output rows, width, etc */ set_baserel_size_estimates(root, rel); @@ -204,7 +205,7 @@ set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) * not the same size. */ static void -set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, +set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte, List *inheritlist) { @@ -217,7 +218,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, * XXX for now, can't handle inherited expansion of FOR UPDATE/SHARE; * can we do better? */ - if (list_member_int(root->rowMarks, parentRTindex)) + if (list_member_int(root->parse->rowMarks, parentRTindex)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE is not supported for inheritance queries"))); @@ -241,7 +242,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, ListCell *parentvars; ListCell *childvars; - childrte = rt_fetch(childRTindex, root->rtable); + childrte = rt_fetch(childRTindex, root->parse->rtable); childOID = childrte->relid; /* @@ -321,12 +322,13 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, * Build the (single) access path for a subquery RTE */ static void -set_subquery_pathlist(Query *root, RelOptInfo *rel, +set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte) { Query *subquery = rte->subquery; bool *differentTypes; List *pathkeys; + List *subquery_pathkeys; /* We need a workspace for keeping track of set-op type coercions */ differentTypes = (bool *) @@ -379,7 +381,8 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel, pfree(differentTypes); /* Generate the plan for the subquery */ - rel->subplan = subquery_planner(subquery, 0.0 /* default case */ ); + rel->subplan = subquery_planner(subquery, 0.0 /* default case */, + &subquery_pathkeys); /* Copy number of output rows from subplan */ rel->tuples = rel->subplan->plan_rows; @@ -388,7 +391,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel, set_baserel_size_estimates(root, rel); /* Convert subquery pathkeys to outer representation */ - pathkeys = build_subquery_pathkeys(root, rel, subquery); + pathkeys = convert_subquery_pathkeys(root, rel, subquery_pathkeys); /* Generate appropriate path */ add_path(rel, create_subqueryscan_path(rel, pathkeys)); @@ -402,7 +405,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel, * Build the (single) access path for a function RTE */ static void -set_function_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) +set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) { /* Mark rel with estimated output rows, width, etc */ set_function_size_estimates(root, rel); @@ -419,7 +422,7 @@ set_function_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) * Build access paths for a FromExpr jointree node. */ RelOptInfo * -make_fromexpr_rel(Query *root, FromExpr *from) +make_fromexpr_rel(PlannerInfo *root, FromExpr *from) { int levels_needed; List *initial_rels = NIL; @@ -483,7 +486,7 @@ make_fromexpr_rel(Query *root, FromExpr *from) * the result of joining all the original relations together. */ static RelOptInfo * -make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels) +make_one_rel_by_joins(PlannerInfo *root, int levels_needed, List *initial_rels) { List **joinitems; int lev; @@ -867,7 +870,7 @@ print_relids(Relids relids) } static void -print_restrictclauses(Query *root, List *clauses) +print_restrictclauses(PlannerInfo *root, List *clauses) { ListCell *l; @@ -875,14 +878,14 @@ print_restrictclauses(Query *root, List *clauses) { RestrictInfo *c = lfirst(l); - print_expr((Node *) c->clause, root->rtable); + print_expr((Node *) c->clause, root->parse->rtable); if (lnext(l)) printf(", "); } } static void -print_path(Query *root, Path *path, int indent) +print_path(PlannerInfo *root, Path *path, int indent) { const char *ptype; bool join = false; @@ -958,7 +961,7 @@ print_path(Query *root, Path *path, int indent) for (i = 0; i < indent; i++) printf("\t"); printf(" pathkeys: "); - print_pathkeys(path->pathkeys, root->rtable); + print_pathkeys(path->pathkeys, root->parse->rtable); } if (join) @@ -994,7 +997,7 @@ print_path(Query *root, Path *path, int indent) } void -debug_print_rel(Query *root, RelOptInfo *rel) +debug_print_rel(PlannerInfo *root, RelOptInfo *rel) { ListCell *l; diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 580a386d3d..f6cd343275 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.72 2004/12/31 22:00:04 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.73 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -92,7 +92,7 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause, * scalarltsel/scalargtsel; perhaps some day we can generalize the approach. */ Selectivity -clauselist_selectivity(Query *root, +clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype) @@ -406,7 +406,7 @@ bms_is_subset_singleton(const Bitmapset *s, int x) * if the clause isn't a join clause or the context is uncertain. */ Selectivity -clause_selectivity(Query *root, +clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype) @@ -476,7 +476,7 @@ clause_selectivity(Query *root, if (var->varlevelsup == 0 && (varRelid == 0 || varRelid == (int) var->varno)) { - RangeTblEntry *rte = rt_fetch(var->varno, root->rtable); + RangeTblEntry *rte = rt_fetch(var->varno, root->parse->rtable); if (rte->rtekind == RTE_SUBQUERY) { diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index c721a85d88..b70b544e22 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -49,7 +49,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.145 2005/04/22 21:58:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.146 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,10 +104,10 @@ bool enable_hashjoin = true; static bool cost_qual_eval_walker(Node *node, QualCost *total); -static Selectivity approx_selectivity(Query *root, List *quals, +static Selectivity approx_selectivity(PlannerInfo *root, List *quals, JoinType jointype); -static Selectivity join_in_selectivity(JoinPath *path, Query *root); -static void set_rel_width(Query *root, RelOptInfo *rel); +static Selectivity join_in_selectivity(JoinPath *path, PlannerInfo *root); +static void set_rel_width(PlannerInfo *root, RelOptInfo *rel); static double relation_byte_size(double tuples, int width); static double page_size(double tuples, int width); @@ -138,7 +138,7 @@ clamp_row_est(double nrows) * Determines and returns the cost of scanning a relation sequentially. */ void -cost_seqscan(Path *path, Query *root, +cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel) { Cost startup_cost = 0; @@ -227,7 +227,6 @@ cost_nonsequential_access(double relpages) * NOTE: an indexscan plan node can actually represent several passes, * but here we consider the cost of just one pass. * - * 'root' is the query root * 'index' is the index to be used * 'indexQuals' is the list of applicable qual clauses (implicit AND semantics) * 'is_injoin' is T if we are considering using the index scan as the inside @@ -246,7 +245,7 @@ cost_nonsequential_access(double relpages) * it was a list of bare clause expressions. */ void -cost_index(IndexPath *path, Query *root, +cost_index(IndexPath *path, PlannerInfo *root, IndexOptInfo *index, List *indexQuals, bool is_injoin) @@ -418,14 +417,13 @@ cost_index(IndexPath *path, Query *root, * Determines and returns the cost of scanning a relation using a bitmap * index-then-heap plan. * - * 'root' is the query root * 'baserel' is the relation to be scanned * 'bitmapqual' is a tree of IndexPaths, BitmapAndPaths, and BitmapOrPaths * 'is_injoin' is T if we are considering using the scan as the inside * of a nestloop join (hence, some of the quals are join clauses) */ void -cost_bitmap_heap_scan(Path *path, Query *root, RelOptInfo *baserel, +cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual, bool is_injoin) { Cost startup_cost = 0; @@ -534,7 +532,7 @@ cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec) * to warrant treating it as one. */ void -cost_bitmap_and_node(BitmapAndPath *path, Query *root) +cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root) { Cost totalCost; Selectivity selec; @@ -577,7 +575,7 @@ cost_bitmap_and_node(BitmapAndPath *path, Query *root) * See comments for cost_bitmap_and_node. */ void -cost_bitmap_or_node(BitmapOrPath *path, Query *root) +cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root) { Cost totalCost; Selectivity selec; @@ -620,7 +618,7 @@ cost_bitmap_or_node(BitmapOrPath *path, Query *root) * Determines and returns the cost of scanning a relation using TIDs. */ void -cost_tidscan(Path *path, Query *root, +cost_tidscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tideval) { Cost startup_cost = 0; @@ -684,7 +682,7 @@ cost_subqueryscan(Path *path, RelOptInfo *baserel) * Determines and returns the cost of scanning a function RTE. */ void -cost_functionscan(Path *path, Query *root, RelOptInfo *baserel) +cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel) { Cost startup_cost = 0; Cost run_cost = 0; @@ -748,7 +746,7 @@ cost_functionscan(Path *path, Query *root, RelOptInfo *baserel) * of sort keys, which all callers *could* supply.) */ void -cost_sort(Path *path, Query *root, +cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width) { Cost startup_cost = input_cost; @@ -857,7 +855,7 @@ cost_material(Path *path, * are for appropriately-sorted input. */ void -cost_agg(Path *path, Query *root, +cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, int numAggs, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, @@ -925,7 +923,7 @@ cost_agg(Path *path, Query *root, * input. */ void -cost_group(Path *path, Query *root, +cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, double input_tuples) @@ -954,7 +952,7 @@ cost_group(Path *path, Query *root, * 'path' is already filled in except for the cost fields */ void -cost_nestloop(NestPath *path, Query *root) +cost_nestloop(NestPath *path, PlannerInfo *root) { Path *outer_path = path->outerjoinpath; Path *inner_path = path->innerjoinpath; @@ -1046,7 +1044,7 @@ cost_nestloop(NestPath *path, Query *root) * sort is needed because the source path is already ordered. */ void -cost_mergejoin(MergePath *path, Query *root) +cost_mergejoin(MergePath *path, PlannerInfo *root) { Path *outer_path = path->jpath.outerjoinpath; Path *inner_path = path->jpath.innerjoinpath; @@ -1275,7 +1273,7 @@ cost_mergejoin(MergePath *path, Query *root) * Note: path's hashclauses should be a subset of the joinrestrictinfo list */ void -cost_hashjoin(HashPath *path, Query *root) +cost_hashjoin(HashPath *path, PlannerInfo *root) { Path *outer_path = path->jpath.outerjoinpath; Path *inner_path = path->jpath.innerjoinpath; @@ -1673,7 +1671,7 @@ cost_qual_eval_walker(Node *node, QualCost *total) * seems OK to live with the approximation. */ static Selectivity -approx_selectivity(Query *root, List *quals, JoinType jointype) +approx_selectivity(PlannerInfo *root, List *quals, JoinType jointype) { Selectivity total = 1.0; ListCell *l; @@ -1703,7 +1701,7 @@ approx_selectivity(Query *root, List *quals, JoinType jointype) * baserestrictcost: estimated cost of evaluating baserestrictinfo clauses. */ void -set_baserel_size_estimates(Query *root, RelOptInfo *rel) +set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) { double nrows; @@ -1749,7 +1747,7 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel) * build_joinrel_tlist, and baserestrictcost is not used for join rels. */ void -set_joinrel_size_estimates(Query *root, RelOptInfo *rel, +set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, @@ -1836,7 +1834,7 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel, * 'path' is already filled in except for the cost fields */ static Selectivity -join_in_selectivity(JoinPath *path, Query *root) +join_in_selectivity(JoinPath *path, PlannerInfo *root) { RelOptInfo *innerrel; UniquePath *innerunique; @@ -1896,7 +1894,7 @@ join_in_selectivity(JoinPath *path, Query *root) * We set the same fields as set_baserel_size_estimates. */ void -set_function_size_estimates(Query *root, RelOptInfo *rel) +set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel) { /* Should only be applied to base relations that are functions */ Assert(rel->relid > 0); @@ -1929,7 +1927,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel) * building join relations. */ static void -set_rel_width(Query *root, RelOptInfo *rel) +set_rel_width(PlannerInfo *root, RelOptInfo *rel) { int32 tuple_width = 0; ListCell *tllist; @@ -1960,7 +1958,7 @@ set_rel_width(Query *root, RelOptInfo *rel) continue; } - relid = getrelid(var->varno, root->rtable); + relid = getrelid(var->varno, root->parse->rtable); if (relid != InvalidOid) { item_width = get_attavgwidth(relid, var->varattno); diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index a6a780f477..0d5a4e99b3 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.180 2005/05/06 17:24:54 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.181 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,13 +55,13 @@ ((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID) -static List *find_usable_indexes(Query *root, RelOptInfo *rel, +static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, bool isjoininner, Relids outer_relids); -static Path *choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths); +static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths); static int bitmap_path_comparator(const void *a, const void *b); -static Cost bitmap_and_cost_est(Query *root, RelOptInfo *rel, List *paths); +static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths); static bool match_clause_to_indexcol(IndexOptInfo *index, int indexcol, Oid opclass, RestrictInfo *rinfo, @@ -75,7 +75,7 @@ static bool list_matches_any_index(List *clauses, RelOptInfo *rel, Relids outer_relids); static bool matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids); -static List *find_clauses_for_join(Query *root, RelOptInfo *rel, +static List *find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel, Relids outer_relids, bool isouterjoin); static bool match_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index); @@ -124,7 +124,7 @@ static Const *string_to_const(const char *str, Oid datatype); * Note: check_partial_indexes() must have been run previously. */ void -create_index_paths(Query *root, RelOptInfo *rel) +create_index_paths(PlannerInfo *root, RelOptInfo *rel) { List *indexpaths; List *bitindexpaths; @@ -231,7 +231,7 @@ create_index_paths(Query *root, RelOptInfo *rel) *---------- */ static List * -find_usable_indexes(Query *root, RelOptInfo *rel, +find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, bool isjoininner, Relids outer_relids) @@ -363,7 +363,7 @@ find_usable_indexes(Query *root, RelOptInfo *rel, * ORs. (See find_usable_indexes() for motivation.) */ List * -generate_bitmap_or_paths(Query *root, RelOptInfo *rel, +generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool isjoininner, Relids outer_relids) @@ -473,7 +473,7 @@ generate_bitmap_or_paths(Query *root, RelOptInfo *rel, * combining multiple inputs. */ static Path * -choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths) +choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) { int npaths = list_length(paths); Path **patharray; @@ -593,7 +593,7 @@ bitmap_path_comparator(const void *a, const void *b) * inputs. */ static Cost -bitmap_and_cost_est(Query *root, RelOptInfo *rel, List *paths) +bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) { BitmapAndPath apath; Path bpath; @@ -864,7 +864,7 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) * depending on whether the predicate is satisfied for this query. */ void -check_partial_indexes(Query *root, RelOptInfo *rel) +check_partial_indexes(PlannerInfo *root, RelOptInfo *rel) { List *restrictinfo_list = rel->baserestrictinfo; ListCell *ilist; @@ -1675,7 +1675,7 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids) * sufficient to return a single "best" path. */ Path * -best_inner_indexscan(Query *root, RelOptInfo *rel, +best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, Relids outer_relids, JoinType jointype) { Path *cheapest; @@ -1828,7 +1828,7 @@ best_inner_indexscan(Query *root, RelOptInfo *rel, * indicating that there isn't any potential win here. */ static List * -find_clauses_for_join(Query *root, RelOptInfo *rel, +find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel, Relids outer_relids, bool isouterjoin) { List *clause_list = NIL; diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 7ee1542ecd..b02f67ba1f 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.94 2005/05/24 18:02:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.95 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,15 +24,15 @@ #include "utils/lsyscache.h" -static void sort_inner_and_outer(Query *root, RelOptInfo *joinrel, +static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, List *mergeclause_list, JoinType jointype); -static void match_unsorted_outer(Query *root, RelOptInfo *joinrel, +static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, List *mergeclause_list, JoinType jointype); -static void hash_inner_and_outer(Query *root, RelOptInfo *joinrel, +static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype); static List *select_mergejoin_clauses(RelOptInfo *joinrel, @@ -54,7 +54,7 @@ static List *select_mergejoin_clauses(RelOptInfo *joinrel, * paths found so far. */ void -add_paths_to_joinrel(Query *root, +add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, @@ -133,7 +133,7 @@ add_paths_to_joinrel(Query *root, * 'jointype' is the type of join to do */ static void -sort_inner_and_outer(Query *root, +sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, @@ -324,7 +324,7 @@ sort_inner_and_outer(Query *root, * 'jointype' is the type of join to do */ static void -match_unsorted_outer(Query *root, +match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, @@ -664,7 +664,7 @@ match_unsorted_outer(Query *root, * 'jointype' is the type of join to do */ static void -hash_inner_and_outer(Query *root, +hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index bc0ac54ca6..a1681ae994 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.72 2004/12/31 22:00:04 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.73 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,13 +18,13 @@ #include "optimizer/paths.h" -static List *make_rels_by_clause_joins(Query *root, +static List *make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, ListCell *other_rels); -static List *make_rels_by_clauseless_joins(Query *root, +static List *make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, ListCell *other_rels); -static bool is_inside_IN(Query *root, RelOptInfo *rel); +static bool is_inside_IN(PlannerInfo *root, RelOptInfo *rel); /* @@ -39,7 +39,7 @@ static bool is_inside_IN(Query *root, RelOptInfo *rel); * joinrels[j], 1 <= j < level, is a list of rels containing j items. */ List * -make_rels_by_joins(Query *root, int level, List **joinrels) +make_rels_by_joins(PlannerInfo *root, int level, List **joinrels) { List *result_rels = NIL; List *new_rels; @@ -284,7 +284,7 @@ make_rels_by_joins(Query *root, int level, List **joinrels) * only succeed when other_rel is not already part of old_rel.) */ static List * -make_rels_by_clause_joins(Query *root, +make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, ListCell *other_rels) { @@ -335,7 +335,7 @@ make_rels_by_clause_joins(Query *root, * work for joining to joinrels too. */ static List * -make_rels_by_clauseless_joins(Query *root, +make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, ListCell *other_rels) { @@ -373,7 +373,7 @@ make_rels_by_clauseless_joins(Query *root, * out of an IN, so the routine name is a slight misnomer. */ static bool -is_inside_IN(Query *root, RelOptInfo *rel) +is_inside_IN(PlannerInfo *root, RelOptInfo *rel) { ListCell *l; @@ -395,7 +395,7 @@ is_inside_IN(Query *root, RelOptInfo *rel) * path that corresponds exactly to what the user wrote. */ RelOptInfo * -make_jointree_rel(Query *root, Node *jtnode) +make_jointree_rel(PlannerInfo *root, Node *jtnode) { if (IsA(jtnode, RangeTblRef)) { @@ -460,7 +460,7 @@ make_jointree_rel(Query *root, Node *jtnode) * happen when working with IN clauses that have been turned into joins. */ RelOptInfo * -make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2, +make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype) { Relids joinrelids; diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index 5ea528ef26..0e2eefc868 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.70 2005/04/25 02:14:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.71 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -79,7 +79,7 @@ *---------- */ bool -create_or_index_quals(Query *root, RelOptInfo *rel) +create_or_index_quals(PlannerInfo *root, RelOptInfo *rel) { BitmapOrPath *bestpath = NULL; RestrictInfo *bestrinfo = NULL; diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 766aa1d116..2994421e5b 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.66 2005/04/06 16:34:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.67 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,8 +32,8 @@ static PathKeyItem *makePathKeyItem(Node *key, Oid sortop, bool checkType); -static List *make_canonical_pathkey(Query *root, PathKeyItem *item); -static Var *find_indexkey_var(Query *root, RelOptInfo *rel, +static List *make_canonical_pathkey(PlannerInfo *root, PathKeyItem *item); +static Var *find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno); @@ -87,7 +87,7 @@ makePathKeyItem(Node *key, Oid sortop, bool checkType) * that involves an equijoined variable. */ void -add_equijoined_keys(Query *root, RestrictInfo *restrictinfo) +add_equijoined_keys(PlannerInfo *root, RestrictInfo *restrictinfo) { Expr *clause = restrictinfo->clause; PathKeyItem *item1 = makePathKeyItem(get_leftop(clause), @@ -198,7 +198,7 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo) * restrictinfo datastructures for each pair. */ void -generate_implied_equalities(Query *root) +generate_implied_equalities(PlannerInfo *root) { ListCell *cursetlink; @@ -293,7 +293,7 @@ generate_implied_equalities(Query *root) * check that case if it's possible to pass identical items. */ bool -exprs_known_equal(Query *root, Node *item1, Node *item2) +exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2) { ListCell *cursetlink; @@ -333,7 +333,7 @@ exprs_known_equal(Query *root, Node *item1, Node *item2) * scanning the WHERE clause for equijoin operators. */ static List * -make_canonical_pathkey(Query *root, PathKeyItem *item) +make_canonical_pathkey(PlannerInfo *root, PathKeyItem *item) { List *newset; ListCell *cursetlink; @@ -358,7 +358,7 @@ make_canonical_pathkey(Query *root, PathKeyItem *item) * scanning the WHERE clause for equijoin operators. */ List * -canonicalize_pathkeys(Query *root, List *pathkeys) +canonicalize_pathkeys(PlannerInfo *root, List *pathkeys) { List *new_pathkeys = NIL; ListCell *l; @@ -398,10 +398,10 @@ canonicalize_pathkeys(Query *root, List *pathkeys) * If not, return 0 (without actually adding it to our equi_key_list). * * This is a hack to support the rather bogus heuristics in - * build_subquery_pathkeys. + * convert_subquery_pathkeys. */ static int -count_canonical_peers(Query *root, PathKeyItem *item) +count_canonical_peers(PlannerInfo *root, PathKeyItem *item) { ListCell *cursetlink; @@ -441,7 +441,7 @@ compare_pathkeys(List *keys1, List *keys2) /* * XXX would like to check that we've been given canonicalized - * input, but query root not accessible here... + * input, but PlannerInfo not accessible here... */ #ifdef NOT_USED Assert(list_member_ptr(root->equi_key_list, subkey1)); @@ -647,7 +647,7 @@ get_cheapest_fractional_path_for_pathkeys(List *paths, * current query. Caller should do truncate_useless_pathkeys(). */ List * -build_index_pathkeys(Query *root, +build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir) { @@ -714,7 +714,7 @@ build_index_pathkeys(Query *root, * gin up a Var node the hard way. */ static Var * -find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno) +find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno) { ListCell *temp; Index relid; @@ -732,24 +732,28 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno) } relid = rel->relid; - reloid = getrelid(relid, root->rtable); + reloid = getrelid(relid, root->parse->rtable); get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod); return makeVar(relid, varattno, vartypeid, type_mod, 0); } /* - * build_subquery_pathkeys + * convert_subquery_pathkeys * Build a pathkeys list that describes the ordering of a subquery's - * result (in the terms of the outer query). The subquery must already - * have been planned, so that its query_pathkeys field has been set. + * result, in the terms of the outer query. This is essentially a + * task of conversion. + * + * 'rel': outer query's RelOptInfo for the subquery relation. + * 'subquery_pathkeys': the subquery's output pathkeys, in its terms. * * It is not necessary for caller to do truncate_useless_pathkeys(), * because we select keys in a way that takes usefulness of the keys into * account. */ List * -build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery) +convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, + List *subquery_pathkeys) { List *retval = NIL; int retvallen = 0; @@ -757,7 +761,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery) List *sub_tlist = rel->subplan->targetlist; ListCell *i; - foreach(i, subquery->query_pathkeys) + foreach(i, subquery_pathkeys) { List *sub_pathkey = (List *) lfirst(i); ListCell *j; @@ -869,7 +873,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery) * Returns the list of new path keys. */ List * -build_join_pathkeys(Query *root, +build_join_pathkeys(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys) @@ -954,7 +958,7 @@ make_pathkeys_for_sortclauses(List *sortclauses, * problem for normal planning, but it is an issue for GEQO planning. */ void -cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo) +cache_mergeclause_pathkeys(PlannerInfo *root, RestrictInfo *restrictinfo) { Node *key; PathKeyItem *item; @@ -1000,7 +1004,7 @@ cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo) * of the join. */ List * -find_mergeclauses_for_pathkeys(Query *root, +find_mergeclauses_for_pathkeys(PlannerInfo *root, List *pathkeys, List *restrictinfos) { @@ -1093,7 +1097,7 @@ find_mergeclauses_for_pathkeys(Query *root, * just make the keys, eh? */ List * -make_pathkeys_for_mergeclauses(Query *root, +make_pathkeys_for_mergeclauses(PlannerInfo *root, List *mergeclauses, RelOptInfo *rel) { @@ -1162,7 +1166,7 @@ make_pathkeys_for_mergeclauses(Query *root, * to be more trouble than it's worth. */ int -pathkeys_useful_for_merging(Query *root, RelOptInfo *rel, List *pathkeys) +pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys) { int useful = 0; ListCell *i; @@ -1226,7 +1230,7 @@ pathkeys_useful_for_merging(Query *root, RelOptInfo *rel, List *pathkeys) * So the result is always either 0 or list_length(root->query_pathkeys). */ int -pathkeys_useful_for_ordering(Query *root, List *pathkeys) +pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys) { if (root->query_pathkeys == NIL) return 0; /* no special ordering requested */ @@ -1248,7 +1252,7 @@ pathkeys_useful_for_ordering(Query *root, List *pathkeys) * Shorten the given pathkey list to just the useful pathkeys. */ List * -truncate_useless_pathkeys(Query *root, +truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys) { diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c index 7468fbf59d..239e20c963 100644 --- a/src/backend/optimizer/path/tidpath.c +++ b/src/backend/optimizer/path/tidpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.22 2004/12/31 22:00:04 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.23 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,11 +25,13 @@ #include "parser/parse_coerce.h" #include "utils/lsyscache.h" + static List *TidqualFromRestrictinfo(Relids relids, List *restrictinfo); static bool isEvaluable(int varno, Node *node); static Node *TidequalClause(int varno, OpExpr *node); static List *TidqualFromExpr(int varno, Expr *expr); + static bool isEvaluable(int varno, Node *node) { @@ -228,7 +230,7 @@ TidqualFromRestrictinfo(Relids relids, List *restrictinfo) * Candidate paths are added to the rel's pathlist (using add_path). */ void -create_tidscan_paths(Query *root, RelOptInfo *rel) +create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel) { List *tideval = TidqualFromRestrictinfo(rel->relids, rel->baserestrictinfo); diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index b743c8348e..5c1142cd0e 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.190 2005/05/30 18:55:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.191 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,36 +35,36 @@ #include "utils/syscache.h" -static Scan *create_scan_plan(Query *root, Path *best_path); +static Scan *create_scan_plan(PlannerInfo *root, Path *best_path); static List *build_relation_tlist(RelOptInfo *rel); static bool use_physical_tlist(RelOptInfo *rel); static void disuse_physical_tlist(Plan *plan, Path *path); -static Join *create_join_plan(Query *root, JoinPath *best_path); -static Append *create_append_plan(Query *root, AppendPath *best_path); -static Result *create_result_plan(Query *root, ResultPath *best_path); -static Material *create_material_plan(Query *root, MaterialPath *best_path); -static Plan *create_unique_plan(Query *root, UniquePath *best_path); -static SeqScan *create_seqscan_plan(Query *root, Path *best_path, +static Join *create_join_plan(PlannerInfo *root, JoinPath *best_path); +static Append *create_append_plan(PlannerInfo *root, AppendPath *best_path); +static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path); +static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path); +static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path); +static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses); -static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path, +static IndexScan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, List **nonlossy_clauses); -static BitmapHeapScan *create_bitmap_scan_plan(Query *root, +static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses); -static Plan *create_bitmap_subplan(Query *root, Path *bitmapqual, +static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual); -static TidScan *create_tidscan_plan(Query *root, TidPath *best_path, +static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses); -static SubqueryScan *create_subqueryscan_plan(Query *root, Path *best_path, +static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses); -static FunctionScan *create_functionscan_plan(Query *root, Path *best_path, +static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses); -static NestLoop *create_nestloop_plan(Query *root, NestPath *best_path, +static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path, Plan *outer_plan, Plan *inner_plan); -static MergeJoin *create_mergejoin_plan(Query *root, MergePath *best_path, +static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path, Plan *outer_plan, Plan *inner_plan); -static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path, +static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path, Plan *outer_plan, Plan *inner_plan); static void fix_indexqual_references(List *indexquals, IndexPath *index_path, List **fixed_indexquals, @@ -112,9 +112,9 @@ static MergeJoin *make_mergejoin(List *tlist, List *mergeclauses, Plan *lefttree, Plan *righttree, JoinType jointype); -static Sort *make_sort(Query *root, Plan *lefttree, int numCols, +static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators); -static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree, +static Sort *make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys); @@ -134,7 +134,7 @@ static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree, * Returns a Plan tree. */ Plan * -create_plan(Query *root, Path *best_path) +create_plan(PlannerInfo *root, Path *best_path) { Plan *plan; @@ -187,7 +187,7 @@ create_plan(Query *root, Path *best_path) * Returns a Plan node. */ static Scan * -create_scan_plan(Query *root, Path *best_path) +create_scan_plan(PlannerInfo *root, Path *best_path) { RelOptInfo *rel = best_path->parent; List *tlist; @@ -376,7 +376,7 @@ disuse_physical_tlist(Plan *plan, Path *path) * Returns a Plan node. */ static Join * -create_join_plan(Query *root, JoinPath *best_path) +create_join_plan(PlannerInfo *root, JoinPath *best_path) { Plan *outer_plan; Plan *inner_plan; @@ -436,7 +436,7 @@ create_join_plan(Query *root, JoinPath *best_path) * Returns a Plan node. */ static Append * -create_append_plan(Query *root, AppendPath *best_path) +create_append_plan(PlannerInfo *root, AppendPath *best_path) { Append *plan; List *tlist = build_relation_tlist(best_path->path.parent); @@ -463,7 +463,7 @@ create_append_plan(Query *root, AppendPath *best_path) * Returns a Plan node. */ static Result * -create_result_plan(Query *root, ResultPath *best_path) +create_result_plan(PlannerInfo *root, ResultPath *best_path) { Result *plan; List *tlist; @@ -495,7 +495,7 @@ create_result_plan(Query *root, ResultPath *best_path) * Returns a Plan node. */ static Material * -create_material_plan(Query *root, MaterialPath *best_path) +create_material_plan(PlannerInfo *root, MaterialPath *best_path) { Material *plan; Plan *subplan; @@ -520,7 +520,7 @@ create_material_plan(Query *root, MaterialPath *best_path) * Returns a Plan node. */ static Plan * -create_unique_plan(Query *root, UniquePath *best_path) +create_unique_plan(PlannerInfo *root, UniquePath *best_path) { Plan *plan; Plan *subplan; @@ -535,7 +535,7 @@ create_unique_plan(Query *root, UniquePath *best_path) subplan = create_plan(root, best_path->subpath); - /* + /*---------- * As constructed, the subplan has a "flat" tlist containing just the * Vars needed here and at upper levels. The values we are supposed * to unique-ify may be expressions in these variables. We have to @@ -545,19 +545,20 @@ create_unique_plan(Query *root, UniquePath *best_path) * existing subplan outputs, not all the output columns may be used * for grouping.) * - * Note: the reason we don't remove any subplan outputs is that there are - * scenarios where a Var is needed at higher levels even though it is - * not one of the nominal outputs of an IN clause. Consider WHERE x - * IN (SELECT y FROM t1,t2 WHERE y = z) Implied equality deduction - * will generate an "x = z" clause, which may get used instead of "x = - * y" in the upper join step. Therefore the sub-select had better - * deliver both y and z in its targetlist. It is sufficient to - * unique-ify on y, however. + * Note: the reason we don't remove any subplan outputs is that there + * are scenarios where a Var is needed at higher levels even though + * it is not one of the nominal outputs of an IN clause. Consider + * WHERE x IN (SELECT y FROM t1,t2 WHERE y = z) + * Implied equality deduction will generate an "x = z" clause, which may + * get used instead of "x = y" in the upper join step. Therefore the + * sub-select had better deliver both y and z in its targetlist. + * It is sufficient to unique-ify on y, however. * * To find the correct list of values to unique-ify, we look in the * information saved for IN expressions. If this code is ever used in * other scenarios, some other way of finding what to unique-ify will * be needed. + *---------- */ uniq_exprs = NIL; /* just to keep compiler quiet */ foreach(l, root->in_info_list) @@ -672,7 +673,7 @@ create_unique_plan(Query *root, UniquePath *best_path) * with restriction clauses 'scan_clauses' and targetlist 'tlist'. */ static SeqScan * -create_seqscan_plan(Query *root, Path *best_path, +create_seqscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses) { SeqScan *scan_plan; @@ -710,7 +711,7 @@ create_seqscan_plan(Query *root, Path *best_path, * nonlossy indexquals. */ static IndexScan * -create_indexscan_plan(Query *root, +create_indexscan_plan(PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, @@ -827,7 +828,7 @@ create_indexscan_plan(Query *root, * with restriction clauses 'scan_clauses' and targetlist 'tlist'. */ static BitmapHeapScan * -create_bitmap_scan_plan(Query *root, +create_bitmap_scan_plan(PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses) @@ -925,7 +926,7 @@ create_bitmap_scan_plan(Query *root, * exclude lossy index operators. */ static Plan * -create_bitmap_subplan(Query *root, Path *bitmapqual, +create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual) { Plan *plan; @@ -1029,7 +1030,7 @@ create_bitmap_subplan(Query *root, Path *bitmapqual, * with restriction clauses 'scan_clauses' and targetlist 'tlist'. */ static TidScan * -create_tidscan_plan(Query *root, TidPath *best_path, +create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses) { TidScan *scan_plan; @@ -1061,7 +1062,7 @@ create_tidscan_plan(Query *root, TidPath *best_path, * with restriction clauses 'scan_clauses' and targetlist 'tlist'. */ static SubqueryScan * -create_subqueryscan_plan(Query *root, Path *best_path, +create_subqueryscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses) { SubqueryScan *scan_plan; @@ -1093,7 +1094,7 @@ create_subqueryscan_plan(Query *root, Path *best_path, * with restriction clauses 'scan_clauses' and targetlist 'tlist'. */ static FunctionScan * -create_functionscan_plan(Query *root, Path *best_path, +create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses) { FunctionScan *scan_plan; @@ -1123,7 +1124,7 @@ create_functionscan_plan(Query *root, Path *best_path, *****************************************************************************/ static NestLoop * -create_nestloop_plan(Query *root, +create_nestloop_plan(PlannerInfo *root, NestPath *best_path, Plan *outer_plan, Plan *inner_plan) @@ -1213,7 +1214,7 @@ create_nestloop_plan(Query *root, } static MergeJoin * -create_mergejoin_plan(Query *root, +create_mergejoin_plan(PlannerInfo *root, MergePath *best_path, Plan *outer_plan, Plan *inner_plan) @@ -1296,7 +1297,7 @@ create_mergejoin_plan(Query *root, } static HashJoin * -create_hashjoin_plan(Query *root, +create_hashjoin_plan(PlannerInfo *root, HashPath *best_path, Plan *outer_plan, Plan *inner_plan) @@ -1608,14 +1609,14 @@ get_switched_clauses(List *clauses, Relids outerrelids) * InitPlan references) to the end of the list. */ List * -order_qual_clauses(Query *root, List *clauses) +order_qual_clauses(PlannerInfo *root, List *clauses) { List *nosubplans; List *withsubplans; ListCell *l; /* No need to work hard if the query is subselect-free */ - if (!root->hasSubLinks) + if (!root->parse->hasSubLinks) return clauses; nosubplans = NIL; @@ -2018,7 +2019,7 @@ make_mergejoin(List *tlist, * Caller must have built the sortColIdx and sortOperators arrays already. */ static Sort * -make_sort(Query *root, Plan *lefttree, int numCols, +make_sort(PlannerInfo *root, Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators) { Sort *node = makeNode(Sort); @@ -2090,7 +2091,7 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, * adding a Result node just to do the projection. */ static Sort * -make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) +make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys) { List *tlist = lefttree->targetlist; ListCell *i; @@ -2201,7 +2202,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) * 'lefttree' is the node which yields input tuples */ Sort * -make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree) +make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree) { List *sub_tlist = lefttree->targetlist; ListCell *l; @@ -2253,7 +2254,7 @@ make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree) * GroupClause entries. */ Sort * -make_sort_from_groupcols(Query *root, +make_sort_from_groupcols(PlannerInfo *root, List *groupcls, AttrNumber *grpColIdx, Plan *lefttree) @@ -2347,7 +2348,7 @@ materialize_finished_plan(Plan *subplan) } Agg * -make_agg(Query *root, List *tlist, List *qual, +make_agg(PlannerInfo *root, List *tlist, List *qual, AggStrategy aggstrategy, int numGroupCols, AttrNumber *grpColIdx, long numGroups, int numAggs, @@ -2412,7 +2413,7 @@ make_agg(Query *root, List *tlist, List *qual, } Group * -make_group(Query *root, +make_group(PlannerInfo *root, List *tlist, List *qual, int numGroupCols, diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 22878c0099..c5b0276379 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.105 2005/04/28 21:47:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.106 2005/06/05 22:32:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,16 +34,16 @@ #include "utils/syscache.h" -static void mark_baserels_for_outer_join(Query *root, Relids rels, +static void mark_baserels_for_outer_join(PlannerInfo *root, Relids rels, Relids outerrels); -static void distribute_qual_to_rels(Query *root, Node *clause, +static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_pushed_down, bool isdeduced, Relids outerjoin_nonnullable, Relids qualscope); -static void add_vars_to_targetlist(Query *root, List *vars, +static void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed); -static bool qual_is_redundant(Query *root, RestrictInfo *restrictinfo, +static bool qual_is_redundant(PlannerInfo *root, RestrictInfo *restrictinfo, List *restrictlist); static void check_mergejoinable(RestrictInfo *restrictinfo); static void check_hashjoinable(RestrictInfo *restrictinfo); @@ -68,7 +68,7 @@ static void check_hashjoinable(RestrictInfo *restrictinfo); * will be used later to build rels for inheritance children. */ void -add_base_rels_to_query(Query *root, Node *jtnode) +add_base_rels_to_query(PlannerInfo *root, Node *jtnode) { if (jtnode == NULL) return; @@ -114,7 +114,7 @@ add_base_rels_to_query(Query *root, Node *jtnode) * propagate up through all join plan steps. */ void -build_base_rel_tlists(Query *root, List *final_tlist) +build_base_rel_tlists(PlannerInfo *root, List *final_tlist) { List *tlist_vars = pull_var_clause((Node *) final_tlist, false); @@ -133,7 +133,7 @@ build_base_rel_tlists(Query *root, List *final_tlist) * where_needed includes "relation 0"). */ static void -add_vars_to_targetlist(Query *root, List *vars, Relids where_needed) +add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed) { ListCell *temp; @@ -189,7 +189,7 @@ add_vars_to_targetlist(Query *root, List *vars, Relids where_needed) * internal convenience; no outside callers pay attention to the result. */ Relids -distribute_quals_to_rels(Query *root, Node *jtnode) +distribute_quals_to_rels(PlannerInfo *root, Node *jtnode) { Relids result = NULL; @@ -306,7 +306,7 @@ distribute_quals_to_rels(Query *root, Node *jtnode) * Mark all base rels listed in 'rels' as having the given outerjoinset. */ static void -mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels) +mark_baserels_for_outer_join(PlannerInfo *root, Relids rels, Relids outerrels) { Relids tmprelids; int relno; @@ -333,7 +333,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels) */ if (rel->outerjoinset == NULL) { - if (list_member_int(root->rowMarks, relno)) + if (list_member_int(root->parse->rowMarks, relno)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE cannot be applied to the nullable side of an outer join"))); @@ -367,7 +367,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels) * 'is_pushed_down' will be TRUE. */ static void -distribute_qual_to_rels(Query *root, Node *clause, +distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_pushed_down, bool isdeduced, Relids outerjoin_nonnullable, @@ -626,7 +626,7 @@ distribute_qual_to_rels(Query *root, Node *clause, * for more details. */ void -process_implied_equality(Query *root, +process_implied_equality(PlannerInfo *root, Node *item1, Node *item2, Oid sortop1, Oid sortop2, Relids item1_relids, Relids item2_relids, @@ -796,7 +796,7 @@ process_implied_equality(Query *root, * all the "var = const" quals. */ static bool -qual_is_redundant(Query *root, +qual_is_redundant(PlannerInfo *root, RestrictInfo *restrictinfo, List *restrictlist) { diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index 38c859dfbc..0a47799707 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.4 2005/04/22 21:58:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.5 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,11 +42,11 @@ typedef struct } MinMaxAggInfo; static bool find_minmax_aggs_walker(Node *node, List **context); -static bool build_minmax_path(Query *root, RelOptInfo *rel, +static bool build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info); static ScanDirection match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol); -static void make_agg_subplan(Query *root, MinMaxAggInfo *info, +static void make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info, List *constant_quals); static Node *replace_aggs_with_params_mutator(Node *node, List **context); static Oid fetch_agg_sort_op(Oid aggfnoid); @@ -61,15 +61,16 @@ static Oid fetch_agg_sort_op(Oid aggfnoid); * Given a suitable index on tab.col, this can be much faster than the * generic scan-all-the-rows plan. * - * We are passed the Query, the preprocessed tlist, and the best path + * We are passed the preprocessed tlist, and the best path * devised for computing the input of a standard Agg node. If we are able * to optimize all the aggregates, and the result is estimated to be cheaper * than the generic aggregate method, then generate and return a Plan that * does it that way. Otherwise, return NULL. */ Plan * -optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) +optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path) { + Query *parse = root->parse; RangeTblRef *rtr; RangeTblEntry *rte; RelOptInfo *rel; @@ -83,11 +84,11 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) List *constant_quals; /* Nothing to do if query has no aggregates */ - if (!root->hasAggs) + if (!parse->hasAggs) return NULL; - Assert(!root->setOperations); /* shouldn't get here if a setop */ - Assert(root->rowMarks == NIL); /* nor if FOR UPDATE */ + Assert(!parse->setOperations); /* shouldn't get here if a setop */ + Assert(parse->rowMarks == NIL); /* nor if FOR UPDATE */ /* * Reject unoptimizable cases. @@ -96,7 +97,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) * grouping require looking at all the rows anyway, and so there's not * much point in optimizing MIN/MAX. */ - if (root->groupClause) + if (parse->groupClause) return NULL; /* @@ -105,13 +106,13 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) * handle a query containing cartesian-product joins, but it hardly * seems worth the trouble.) */ - Assert(root->jointree != NULL && IsA(root->jointree, FromExpr)); - if (list_length(root->jointree->fromlist) != 1) + Assert(parse->jointree != NULL && IsA(parse->jointree, FromExpr)); + if (list_length(parse->jointree->fromlist) != 1) return NULL; - rtr = (RangeTblRef *) linitial(root->jointree->fromlist); + rtr = (RangeTblRef *) linitial(parse->jointree->fromlist); if (!IsA(rtr, RangeTblRef)) return NULL; - rte = rt_fetch(rtr->rtindex, root->rtable); + rte = rt_fetch(rtr->rtindex, parse->rtable); if (rte->rtekind != RTE_RELATION) return NULL; rel = find_base_rel(root, rtr->rtindex); @@ -121,8 +122,8 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) * This may be overly paranoid, but it's not entirely clear if the * transformation is safe then. */ - if (contain_subplans(root->jointree->quals) || - contain_volatile_functions(root->jointree->quals)) + if (contain_subplans(parse->jointree->quals) || + contain_volatile_functions(parse->jointree->quals)) return NULL; /* @@ -143,7 +144,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) aggs_list = NIL; if (find_minmax_aggs_walker((Node *) tlist, &aggs_list)) return NULL; - if (find_minmax_aggs_walker(root->havingQual, &aggs_list)) + if (find_minmax_aggs_walker(parse->havingQual, &aggs_list)) return NULL; /* Pass 2: see if each one is optimizable */ @@ -202,7 +203,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path) */ tlist = (List *) replace_aggs_with_params_mutator((Node *) tlist, &aggs_list); - hqual = replace_aggs_with_params_mutator(root->havingQual, + hqual = replace_aggs_with_params_mutator(parse->havingQual, &aggs_list); /* @@ -298,7 +299,7 @@ find_minmax_aggs_walker(Node *node, List **context) * Note: check_partial_indexes() must have been run previously. */ static bool -build_minmax_path(Query *root, RelOptInfo *rel, MinMaxAggInfo *info) +build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info) { IndexPath *best_path = NULL; Cost best_cost = 0; @@ -441,46 +442,48 @@ match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol) * Construct a suitable plan for a converted aggregate query */ static void -make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals) +make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info, List *constant_quals) { - Query *subquery; + PlannerInfo subroot; + Query *subparse; Plan *plan; TargetEntry *tle; SortClause *sortcl; NullTest *ntest; /* - * Generate a suitably modified Query node. Much of the work here is + * Generate a suitably modified query. Much of the work here is * probably unnecessary in the normal case, but we want to make it look * good if someone tries to EXPLAIN the result. */ - subquery = (Query *) copyObject(root); - subquery->commandType = CMD_SELECT; - subquery->resultRelation = 0; - subquery->resultRelations = NIL; - subquery->into = NULL; - subquery->hasAggs = false; - subquery->groupClause = NIL; - subquery->havingQual = NULL; - subquery->hasHavingQual = false; - subquery->distinctClause = NIL; + memcpy(&subroot, root, sizeof(PlannerInfo)); + subroot.parse = subparse = (Query *) copyObject(root->parse); + subparse->commandType = CMD_SELECT; + subparse->resultRelation = 0; + subparse->resultRelations = NIL; + subparse->into = NULL; + subparse->hasAggs = false; + subparse->groupClause = NIL; + subparse->havingQual = NULL; + subparse->distinctClause = NIL; + subroot.hasHavingQual = false; /* single tlist entry that is the aggregate target */ tle = makeTargetEntry(copyObject(info->target), 1, pstrdup("agg_target"), false); - subquery->targetList = list_make1(tle); + subparse->targetList = list_make1(tle); /* set up the appropriate ORDER BY entry */ sortcl = makeNode(SortClause); - sortcl->tleSortGroupRef = assignSortGroupRef(tle, subquery->targetList); + sortcl->tleSortGroupRef = assignSortGroupRef(tle, subparse->targetList); sortcl->sortop = info->aggsortop; - subquery->sortClause = list_make1(sortcl); + subparse->sortClause = list_make1(sortcl); /* set up LIMIT 1 */ - subquery->limitOffset = NULL; - subquery->limitCount = (Node *) makeConst(INT4OID, sizeof(int4), + subparse->limitOffset = NULL; + subparse->limitCount = (Node *) makeConst(INT4OID, sizeof(int4), Int32GetDatum(1), false, true); @@ -498,9 +501,9 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals) * most cases the fraction of NULLs isn't high enough to change the * decision. */ - plan = create_plan(subquery, (Path *) info->path); + plan = create_plan(&subroot, (Path *) info->path); - plan->targetlist = copyObject(subquery->targetList); + plan->targetlist = copyObject(subparse->targetList); ntest = makeNode(NullTest); ntest->nulltesttype = IS_NOT_NULL; @@ -514,13 +517,13 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals) plan); plan = (Plan *) make_limit(plan, - subquery->limitOffset, - subquery->limitCount); + subparse->limitOffset, + subparse->limitCount); /* * Convert the plan into an InitPlan, and make a Param for its result. */ - info->param = SS_make_initplan_from_plan(subquery, plan, + info->param = SS_make_initplan_from_plan(&subroot, plan, exprType((Node *) tle->expr), -1); } diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index 78b2d127fa..79a28cae3a 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.81 2004/12/31 22:00:09 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.82 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,8 +42,9 @@ * will make the final decision about which to use. * * Input parameters: - * root is the query to plan - * tlist is the target list the query should produce (NOT root->targetList!) + * root describes the query to plan + * tlist is the target list the query should produce + * (this is NOT necessarily root->parse->targetList!) * tuple_fraction is the fraction of tuples we expect will be retrieved * * Output parameters: @@ -51,14 +52,14 @@ * *sorted_path receives the cheapest presorted path for the query, * if any (NULL if there is no useful presorted path) * - * Note: the Query node also includes a query_pathkeys field, which is both - * an input and an output of query_planner(). The input value signals + * Note: the PlannerInfo node also includes a query_pathkeys field, which is + * both an input and an output of query_planner(). The input value signals * query_planner that the indicated sort order is wanted in the final output * plan. But this value has not yet been "canonicalized", since the needed * info does not get computed until we scan the qual clauses. We canonicalize * it as soon as that task is done. (The main reason query_pathkeys is a - * Query field and not a passed parameter is that the low-level routines in - * indxpath.c need to see it.) + * PlannerInfo field and not a passed parameter is that the low-level routines + * in indxpath.c need to see it.) * * tuple_fraction is interpreted as follows: * 0: expect all tuples to be retrieved (normal case) @@ -69,9 +70,10 @@ *-------------------- */ void -query_planner(Query *root, List *tlist, double tuple_fraction, +query_planner(PlannerInfo *root, List *tlist, double tuple_fraction, Path **cheapest_path, Path **sorted_path) { + Query *parse = root->parse; List *constant_quals; RelOptInfo *final_rel; Path *cheapestpath; @@ -81,10 +83,10 @@ query_planner(Query *root, List *tlist, double tuple_fraction, * If the query has an empty join tree, then it's something easy like * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly. */ - if (root->jointree->fromlist == NIL) + if (parse->jointree->fromlist == NIL) { *cheapest_path = (Path *) create_result_path(NULL, NULL, - (List *) root->jointree->quals); + (List *) parse->jointree->quals); *sorted_path = NULL; return; } @@ -99,8 +101,8 @@ query_planner(Query *root, List *tlist, double tuple_fraction, * vars, although if the qual reduces to "WHERE FALSE" this path will * also be taken. */ - root->jointree->quals = (Node *) - pull_constant_clauses((List *) root->jointree->quals, + parse->jointree->quals = (Node *) + pull_constant_clauses((List *) parse->jointree->quals, &constant_quals); /* @@ -116,7 +118,7 @@ query_planner(Query *root, List *tlist, double tuple_fraction, /* * Construct RelOptInfo nodes for all base relations in query. */ - add_base_rels_to_query(root, (Node *) root->jointree); + add_base_rels_to_query(root, (Node *) parse->jointree); /* * Examine the targetlist and qualifications, adding entries to @@ -133,7 +135,7 @@ query_planner(Query *root, List *tlist, double tuple_fraction, */ build_base_rel_tlists(root, tlist); - (void) distribute_quals_to_rels(root, (Node *) root->jointree); + (void) distribute_quals_to_rels(root, (Node *) parse->jointree); /* * Use the completed lists of equijoined keys to deduce any implied diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 858f960aaf..76ffe04078 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.187 2005/05/30 01:04:44 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.188 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -54,18 +54,18 @@ ParamListInfo PlannerBoundParamList = NULL; /* current boundParams */ #define EXPRKIND_ININFO 4 -static Node *preprocess_expression(Query *parse, Node *expr, int kind); -static void preprocess_qual_conditions(Query *parse, Node *jtnode); -static Plan *inheritance_planner(Query *parse, List *inheritlist); -static Plan *grouping_planner(Query *parse, double tuple_fraction); -static bool choose_hashed_grouping(Query *parse, double tuple_fraction, +static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); +static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode); +static Plan *inheritance_planner(PlannerInfo *root, List *inheritlist); +static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction); +static bool choose_hashed_grouping(PlannerInfo *root, double tuple_fraction, Path *cheapest_path, Path *sorted_path, List *sort_pathkeys, List *group_pathkeys, double dNumGroups, AggClauseCounts *agg_counts); -static bool hash_safe_grouping(Query *parse); -static List *make_subplanTargetList(Query *parse, List *tlist, +static bool hash_safe_grouping(PlannerInfo *root); +static List *make_subplanTargetList(PlannerInfo *root, List *tlist, AttrNumber **groupColIdx, bool *need_tlist_eval); -static void locate_grouping_columns(Query *parse, +static void locate_grouping_columns(PlannerInfo *root, List *tlist, List *sub_tlist, AttrNumber *groupColIdx); @@ -92,10 +92,10 @@ planner(Query *parse, bool isCursor, int cursorOptions, * eval_const_expressions tries to pre-evaluate an SQL function). So, * these global state variables must be saved and restored. * - * Query level and the param list cannot be moved into the Query - * structure since their whole purpose is communication across - * multiple sub-Queries. Also, boundParams is explicitly info from - * outside the Query, and so is likewise better handled as a global + * Query level and the param list cannot be moved into the per-query + * PlannerInfo structure since their whole purpose is communication + * across multiple sub-queries. Also, boundParams is explicitly info + * from outside the query, and so is likewise better handled as a global * variable. * * Note we do NOT save and restore PlannerPlanId: it exists to assign @@ -130,8 +130,9 @@ planner(Query *parse, bool isCursor, int cursorOptions, } /* primary planning entry point (may recurse for subqueries) */ - result_plan = subquery_planner(parse, tuple_fraction); + result_plan = subquery_planner(parse, tuple_fraction, NULL); + /* check we popped out the right number of levels */ Assert(PlannerQueryLevel == 0); /* @@ -168,6 +169,9 @@ planner(Query *parse, bool isCursor, int cursorOptions, * tuple_fraction is the fraction of tuples we expect will be retrieved. * tuple_fraction is interpreted as explained for grouping_planner, below. * + * If subquery_pathkeys isn't NULL, it receives a list of pathkeys indicating + * the output sort ordering of the completed plan. + * * Basically, this routine does the stuff that should only be done once * per Query object. It then calls grouping_planner. At one time, * grouping_planner could be invoked recursively on the same Query object; @@ -181,12 +185,14 @@ planner(Query *parse, bool isCursor, int cursorOptions, *-------------------- */ Plan * -subquery_planner(Query *parse, double tuple_fraction) +subquery_planner(Query *parse, double tuple_fraction, + List **subquery_pathkeys) { List *saved_initplan = PlannerInitPlan; int saved_planid = PlannerPlanId; - bool hasOuterJoins; + PlannerInfo *root; Plan *plan; + bool hasOuterJoins; List *newHaving; List *lst; ListCell *l; @@ -195,23 +201,27 @@ subquery_planner(Query *parse, double tuple_fraction) PlannerQueryLevel++; PlannerInitPlan = NIL; + /* Create a PlannerInfo data structure for this subquery */ + root = makeNode(PlannerInfo); + root->parse = parse; + /* * Look for IN clauses at the top level of WHERE, and transform them * into joins. Note that this step only handles IN clauses originally * at top level of WHERE; if we pull up any subqueries in the next * step, their INs are processed just before pulling them up. */ - parse->in_info_list = NIL; + root->in_info_list = NIL; if (parse->hasSubLinks) - parse->jointree->quals = pull_up_IN_clauses(parse, - parse->jointree->quals); + parse->jointree->quals = pull_up_IN_clauses(root, + parse->jointree->quals); /* * Check to see if any subqueries in the rangetable can be merged into * this query. */ parse->jointree = (FromExpr *) - pull_up_subqueries(parse, (Node *) parse->jointree, false); + pull_up_subqueries(root, (Node *) parse->jointree, false); /* * Detect whether any rangetable entries are RTE_JOIN kind; if not, we @@ -220,7 +230,7 @@ subquery_planner(Query *parse, double tuple_fraction) * reduce_outer_joins(). This must be done after we have done * pull_up_subqueries, of course. */ - parse->hasJoinRTEs = false; + root->hasJoinRTEs = false; hasOuterJoins = false; foreach(l, parse->rtable) { @@ -228,7 +238,7 @@ subquery_planner(Query *parse, double tuple_fraction) if (rte->rtekind == RTE_JOIN) { - parse->hasJoinRTEs = true; + root->hasJoinRTEs = true; if (IS_OUTER_JOIN(rte->jointype)) { hasOuterJoins = true; @@ -243,27 +253,27 @@ subquery_planner(Query *parse, double tuple_fraction) * because preprocess_expression will reduce a constant-true condition * to an empty qual list ... but "HAVING TRUE" is not a semantic no-op. */ - parse->hasHavingQual = (parse->havingQual != NULL); + root->hasHavingQual = (parse->havingQual != NULL); /* * Do expression preprocessing on targetlist and quals. */ parse->targetList = (List *) - preprocess_expression(parse, (Node *) parse->targetList, + preprocess_expression(root, (Node *) parse->targetList, EXPRKIND_TARGET); - preprocess_qual_conditions(parse, (Node *) parse->jointree); + preprocess_qual_conditions(root, (Node *) parse->jointree); - parse->havingQual = preprocess_expression(parse, parse->havingQual, + parse->havingQual = preprocess_expression(root, parse->havingQual, EXPRKIND_QUAL); - parse->limitOffset = preprocess_expression(parse, parse->limitOffset, + parse->limitOffset = preprocess_expression(root, parse->limitOffset, EXPRKIND_LIMIT); - parse->limitCount = preprocess_expression(parse, parse->limitCount, + parse->limitCount = preprocess_expression(root, parse->limitCount, EXPRKIND_LIMIT); - parse->in_info_list = (List *) - preprocess_expression(parse, (Node *) parse->in_info_list, + root->in_info_list = (List *) + preprocess_expression(root, (Node *) root->in_info_list, EXPRKIND_ININFO); /* Also need to preprocess expressions for function RTEs */ @@ -272,7 +282,7 @@ subquery_planner(Query *parse, double tuple_fraction) RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); if (rte->rtekind == RTE_FUNCTION) - rte->funcexpr = preprocess_expression(parse, rte->funcexpr, + rte->funcexpr = preprocess_expression(root, rte->funcexpr, EXPRKIND_RTFUNC); } @@ -336,7 +346,7 @@ subquery_planner(Query *parse, double tuple_fraction) * preprocessing. */ if (hasOuterJoins) - reduce_outer_joins(parse); + reduce_outer_joins(root); /* * See if we can simplify the jointree; opportunities for this may @@ -347,7 +357,7 @@ subquery_planner(Query *parse, double tuple_fraction) * after reduce_outer_joins, anyway. */ parse->jointree = (FromExpr *) - simplify_jointree(parse, (Node *) parse->jointree); + simplify_jointree(root, (Node *) parse->jointree); /* * Do the main planning. If we have an inherited target relation, @@ -355,10 +365,10 @@ subquery_planner(Query *parse, double tuple_fraction) * grouping_planner. */ if (parse->resultRelation && - (lst = expand_inherited_rtentry(parse, parse->resultRelation)) != NIL) - plan = inheritance_planner(parse, lst); + (lst = expand_inherited_rtentry(root, parse->resultRelation)) != NIL) + plan = inheritance_planner(root, lst); else - plan = grouping_planner(parse, tuple_fraction); + plan = grouping_planner(root, tuple_fraction); /* * If any subplans were generated, or if we're inside a subplan, build @@ -368,6 +378,10 @@ subquery_planner(Query *parse, double tuple_fraction) if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1) SS_finalize_plan(plan, parse->rtable); + /* Return sort ordering info if caller wants it */ + if (subquery_pathkeys) + *subquery_pathkeys = root->query_pathkeys; + /* Return to outer subquery context */ PlannerQueryLevel--; PlannerInitPlan = saved_initplan; @@ -383,7 +397,7 @@ subquery_planner(Query *parse, double tuple_fraction) * conditions), or a HAVING clause. */ static Node * -preprocess_expression(Query *parse, Node *expr, int kind) +preprocess_expression(PlannerInfo *root, Node *expr, int kind) { /* * Fall out quickly if expression is empty. This occurs often enough @@ -399,8 +413,8 @@ preprocess_expression(Query *parse, Node *expr, int kind) * else sublinks expanded out from join aliases wouldn't get * processed. */ - if (parse->hasJoinRTEs) - expr = flatten_join_alias_vars(parse, expr); + if (root->hasJoinRTEs) + expr = flatten_join_alias_vars(root, expr); /* * Simplify constant expressions. @@ -418,7 +432,7 @@ preprocess_expression(Query *parse, Node *expr, int kind) * 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. */ - if (parse->jointree->fromlist != NIL || + if (root->parse->jointree->fromlist != NIL || kind == EXPRKIND_QUAL || PlannerQueryLevel > 1) expr = eval_const_expressions(expr); @@ -437,7 +451,7 @@ preprocess_expression(Query *parse, Node *expr, int kind) } /* Expand SubLinks to SubPlans */ - if (parse->hasSubLinks) + if (root->parse->hasSubLinks) expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL)); /* @@ -467,7 +481,7 @@ preprocess_expression(Query *parse, Node *expr, int kind) * preprocessing work on each qual condition found therein. */ static void -preprocess_qual_conditions(Query *parse, Node *jtnode) +preprocess_qual_conditions(PlannerInfo *root, Node *jtnode) { if (jtnode == NULL) return; @@ -481,18 +495,18 @@ preprocess_qual_conditions(Query *parse, Node *jtnode) ListCell *l; foreach(l, f->fromlist) - preprocess_qual_conditions(parse, lfirst(l)); + preprocess_qual_conditions(root, lfirst(l)); - f->quals = preprocess_expression(parse, f->quals, EXPRKIND_QUAL); + f->quals = preprocess_expression(root, f->quals, EXPRKIND_QUAL); } else if (IsA(jtnode, JoinExpr)) { JoinExpr *j = (JoinExpr *) jtnode; - preprocess_qual_conditions(parse, j->larg); - preprocess_qual_conditions(parse, j->rarg); + preprocess_qual_conditions(root, j->larg); + preprocess_qual_conditions(root, j->rarg); - j->quals = preprocess_expression(parse, j->quals, EXPRKIND_QUAL); + j->quals = preprocess_expression(root, j->quals, EXPRKIND_QUAL); } else elog(ERROR, "unrecognized node type: %d", @@ -514,15 +528,15 @@ preprocess_qual_conditions(Query *parse, Node *jtnode) * can never be the nullable side of an outer join, so it's OK to generate * the plan this way. * - * parse is the querytree produced by the parser & rewriter. * inheritlist is an integer list of RT indexes for the result relation set. * * Returns a query plan. *-------------------- */ static Plan * -inheritance_planner(Query *parse, List *inheritlist) +inheritance_planner(PlannerInfo *root, List *inheritlist) { + Query *parse = root->parse; int parentRTindex = parse->resultRelation; Oid parentOID = getrelid(parentRTindex, parse->rtable); int mainrtlength = list_length(parse->rtable); @@ -534,15 +548,27 @@ inheritance_planner(Query *parse, List *inheritlist) { int childRTindex = lfirst_int(l); Oid childOID = getrelid(childRTindex, parse->rtable); - Query *subquery; + PlannerInfo subroot; Plan *subplan; - /* Generate modified query with this rel as target */ - subquery = (Query *) adjust_inherited_attrs((Node *) parse, - parentRTindex, parentOID, - childRTindex, childOID); + /* + * Generate modified query with this rel as target. We have to + * be prepared to translate varnos in in_info_list as well as in + * the Query proper. + */ + memcpy(&subroot, root, sizeof(PlannerInfo)); + subroot.parse = (Query *) + adjust_inherited_attrs((Node *) parse, + parentRTindex, parentOID, + childRTindex, childOID); + subroot.in_info_list = (List *) + adjust_inherited_attrs((Node *) root->in_info_list, + parentRTindex, parentOID, + childRTindex, childOID); + /* Generate plan */ - subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ ); + subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ ); + subplans = lappend(subplans, subplan); /* @@ -565,16 +591,16 @@ inheritance_planner(Query *parse, List *inheritlist) * rangetables will be the same each time. Did I say this is ugly?) */ if (lnext(l) == NULL) - parse->rtable = subquery->rtable; + parse->rtable = subroot.parse->rtable; else { - int subrtlength = list_length(subquery->rtable); + int subrtlength = list_length(subroot.parse->rtable); if (subrtlength > mainrtlength) { List *subrt; - subrt = list_copy_tail(subquery->rtable, mainrtlength); + subrt = list_copy_tail(subroot.parse->rtable, mainrtlength); parse->rtable = list_concat(parse->rtable, subrt); mainrtlength = subrtlength; } @@ -589,7 +615,7 @@ inheritance_planner(Query *parse, List *inheritlist) parse->resultRelations = inheritlist; /* Mark result as unordered (probably unnecessary) */ - parse->query_pathkeys = NIL; + root->query_pathkeys = NIL; return (Plan *) make_append(subplans, true, tlist); } @@ -600,7 +626,6 @@ inheritance_planner(Query *parse, List *inheritlist) * This primarily means adding top-level processing to the basic * query plan produced by query_planner. * - * parse is the querytree produced by the parser & rewriter. * tuple_fraction is the fraction of tuples we expect will be retrieved * * tuple_fraction is interpreted as follows: @@ -610,13 +635,14 @@ inheritance_planner(Query *parse, List *inheritlist) * tuple_fraction >= 1: tuple_fraction is the absolute number of tuples * expected to be retrieved (ie, a LIMIT specification) * - * Returns a query plan. Also, parse->query_pathkeys is returned as the + * Returns a query plan. Also, root->query_pathkeys is returned as the * actual output ordering of the plan (in pathkey format). *-------------------- */ static Plan * -grouping_planner(Query *parse, double tuple_fraction) +grouping_planner(PlannerInfo *root, double tuple_fraction) { + Query *parse = root->parse; List *tlist = parse->targetList; Plan *result_plan; List *current_pathkeys; @@ -630,7 +656,7 @@ grouping_planner(Query *parse, double tuple_fraction) * Construct the plan for set operations. The result will not * need any work except perhaps a top-level sort and/or LIMIT. */ - result_plan = plan_set_operations(parse, + result_plan = plan_set_operations(root, &set_sortclauses); /* @@ -640,7 +666,7 @@ grouping_planner(Query *parse, double tuple_fraction) */ current_pathkeys = make_pathkeys_for_sortclauses(set_sortclauses, result_plan->targetlist); - current_pathkeys = canonicalize_pathkeys(parse, current_pathkeys); + current_pathkeys = canonicalize_pathkeys(root, current_pathkeys); /* * We should not need to call preprocess_targetlist, since we must @@ -667,7 +693,7 @@ grouping_planner(Query *parse, double tuple_fraction) */ sort_pathkeys = make_pathkeys_for_sortclauses(parse->sortClause, tlist); - sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys); + sort_pathkeys = canonicalize_pathkeys(root, sort_pathkeys); } else { @@ -690,13 +716,13 @@ grouping_planner(Query *parse, double tuple_fraction) MemSet(&agg_counts, 0, sizeof(AggClauseCounts)); /* Preprocess targetlist */ - tlist = preprocess_targetlist(parse, tlist); + tlist = preprocess_targetlist(root, tlist); /* * Generate appropriate target list for subplan; may be different * from tlist if grouping or aggregation is needed. */ - sub_tlist = make_subplanTargetList(parse, tlist, + sub_tlist = make_subplanTargetList(root, tlist, &groupColIdx, &need_tlist_eval); /* @@ -737,11 +763,11 @@ grouping_planner(Query *parse, double tuple_fraction) * Needs more thought...) */ if (parse->groupClause) - parse->query_pathkeys = group_pathkeys; + root->query_pathkeys = group_pathkeys; else if (parse->sortClause) - parse->query_pathkeys = sort_pathkeys; + root->query_pathkeys = sort_pathkeys; else - parse->query_pathkeys = NIL; + root->query_pathkeys = NIL; /* * Adjust tuple_fraction if we see that we are going to apply @@ -902,15 +928,15 @@ grouping_planner(Query *parse, double tuple_fraction) * Generate the best unsorted and presorted paths for this Query * (but note there may not be any presorted path). */ - query_planner(parse, sub_tlist, sub_tuple_fraction, + query_planner(root, sub_tlist, sub_tuple_fraction, &cheapest_path, &sorted_path); /* * We couldn't canonicalize group_pathkeys and sort_pathkeys * before running query_planner(), so do it now. */ - group_pathkeys = canonicalize_pathkeys(parse, group_pathkeys); - sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys); + group_pathkeys = canonicalize_pathkeys(root, group_pathkeys); + sort_pathkeys = canonicalize_pathkeys(root, sort_pathkeys); /* * If grouping, estimate the number of groups. (We can't do this @@ -934,14 +960,14 @@ grouping_planner(Query *parse, double tuple_fraction) groupExprs = get_sortgrouplist_exprs(parse->groupClause, parse->targetList); - dNumGroups = estimate_num_groups(parse, + dNumGroups = estimate_num_groups(root, groupExprs, cheapest_path_rows); /* Also want it as a long int --- but 'ware overflow! */ numGroups = (long) Min(dNumGroups, (double) LONG_MAX); use_hashed_grouping = - choose_hashed_grouping(parse, tuple_fraction, + choose_hashed_grouping(root, tuple_fraction, cheapest_path, sorted_path, sort_pathkeys, group_pathkeys, dNumGroups, &agg_counts); @@ -963,7 +989,7 @@ grouping_planner(Query *parse, double tuple_fraction) * "regular" path ... but we had to do it anyway to be able to * tell which way is cheaper. */ - result_plan = optimize_minmax_aggregates(parse, + result_plan = optimize_minmax_aggregates(root, tlist, best_path); if (result_plan != NULL) @@ -980,7 +1006,7 @@ grouping_planner(Query *parse, double tuple_fraction) * Normal case --- create a plan according to query_planner's * results. */ - result_plan = create_plan(parse, best_path); + result_plan = create_plan(root, best_path); current_pathkeys = best_path->pathkeys; /* @@ -1042,7 +1068,7 @@ grouping_planner(Query *parse, double tuple_fraction) * make_subplanTargetList calculated, we have to refigure any * grouping-column indexes make_subplanTargetList computed. */ - locate_grouping_columns(parse, tlist, result_plan->targetlist, + locate_grouping_columns(root, tlist, result_plan->targetlist, groupColIdx); } @@ -1055,7 +1081,7 @@ grouping_planner(Query *parse, double tuple_fraction) if (use_hashed_grouping) { /* Hashed aggregate plan --- no sort needed */ - result_plan = (Plan *) make_agg(parse, + result_plan = (Plan *) make_agg(root, tlist, (List *) parse->havingQual, AGG_HASHED, @@ -1078,7 +1104,7 @@ grouping_planner(Query *parse, double tuple_fraction) current_pathkeys)) { result_plan = (Plan *) - make_sort_from_groupcols(parse, + make_sort_from_groupcols(root, parse->groupClause, groupColIdx, result_plan); @@ -1098,7 +1124,7 @@ grouping_planner(Query *parse, double tuple_fraction) current_pathkeys = NIL; } - result_plan = (Plan *) make_agg(parse, + result_plan = (Plan *) make_agg(root, tlist, (List *) parse->havingQual, aggstrategy, @@ -1120,14 +1146,14 @@ grouping_planner(Query *parse, double tuple_fraction) if (!pathkeys_contained_in(group_pathkeys, current_pathkeys)) { result_plan = (Plan *) - make_sort_from_groupcols(parse, + make_sort_from_groupcols(root, parse->groupClause, groupColIdx, result_plan); current_pathkeys = group_pathkeys; } - result_plan = (Plan *) make_group(parse, + result_plan = (Plan *) make_group(root, tlist, (List *) parse->havingQual, numGroupCols, @@ -1136,7 +1162,7 @@ grouping_planner(Query *parse, double tuple_fraction) result_plan); /* The Group node won't change sort ordering */ } - else if (parse->hasHavingQual) + else if (root->hasHavingQual) { /* * No aggregates, and no GROUP BY, but we have a HAVING qual. @@ -1165,7 +1191,7 @@ grouping_planner(Query *parse, double tuple_fraction) if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys)) { result_plan = (Plan *) - make_sort_from_sortclauses(parse, + make_sort_from_sortclauses(root, parse->sortClause, result_plan); current_pathkeys = sort_pathkeys; @@ -1185,13 +1211,13 @@ grouping_planner(Query *parse, double tuple_fraction) * it's reasonable to assume the UNIQUE filter has effects * comparable to GROUP BY. */ - if (!parse->groupClause && !parse->hasHavingQual && !parse->hasAggs) + if (!parse->groupClause && !root->hasHavingQual && !parse->hasAggs) { List *distinctExprs; distinctExprs = get_sortgrouplist_exprs(parse->distinctClause, parse->targetList); - result_plan->plan_rows = estimate_num_groups(parse, + result_plan->plan_rows = estimate_num_groups(root, distinctExprs, result_plan->plan_rows); } @@ -1211,7 +1237,7 @@ grouping_planner(Query *parse, double tuple_fraction) * Return the actual output ordering in query_pathkeys for possible * use by an outer query level. */ - parse->query_pathkeys = current_pathkeys; + root->query_pathkeys = current_pathkeys; return result_plan; } @@ -1220,12 +1246,12 @@ grouping_planner(Query *parse, double tuple_fraction) * choose_hashed_grouping - should we use hashed grouping? */ static bool -choose_hashed_grouping(Query *parse, double tuple_fraction, +choose_hashed_grouping(PlannerInfo *root, double tuple_fraction, Path *cheapest_path, Path *sorted_path, List *sort_pathkeys, List *group_pathkeys, double dNumGroups, AggClauseCounts *agg_counts) { - int numGroupCols = list_length(parse->groupClause); + int numGroupCols = list_length(root->parse->groupClause); double cheapest_path_rows; int cheapest_path_width; Size hashentrysize; @@ -1245,7 +1271,7 @@ choose_hashed_grouping(Query *parse, double tuple_fraction, return false; if (agg_counts->numDistinctAggs != 0) return false; - if (!hash_safe_grouping(parse)) + if (!hash_safe_grouping(root)) return false; /* @@ -1296,13 +1322,13 @@ choose_hashed_grouping(Query *parse, double tuple_fraction, * These path variables are dummies that just hold cost fields; we don't * make actual Paths for these steps. */ - cost_agg(&hashed_p, parse, AGG_HASHED, agg_counts->numAggs, + cost_agg(&hashed_p, root, AGG_HASHED, agg_counts->numAggs, numGroupCols, dNumGroups, cheapest_path->startup_cost, cheapest_path->total_cost, cheapest_path_rows); /* Result of hashed agg is always unsorted */ if (sort_pathkeys) - cost_sort(&hashed_p, parse, sort_pathkeys, hashed_p.total_cost, + cost_sort(&hashed_p, root, sort_pathkeys, hashed_p.total_cost, dNumGroups, cheapest_path_width); if (sorted_path) @@ -1320,24 +1346,24 @@ choose_hashed_grouping(Query *parse, double tuple_fraction, if (!pathkeys_contained_in(group_pathkeys, current_pathkeys)) { - cost_sort(&sorted_p, parse, group_pathkeys, sorted_p.total_cost, + cost_sort(&sorted_p, root, group_pathkeys, sorted_p.total_cost, cheapest_path_rows, cheapest_path_width); current_pathkeys = group_pathkeys; } - if (parse->hasAggs) - cost_agg(&sorted_p, parse, AGG_SORTED, agg_counts->numAggs, + if (root->parse->hasAggs) + cost_agg(&sorted_p, root, AGG_SORTED, agg_counts->numAggs, numGroupCols, dNumGroups, sorted_p.startup_cost, sorted_p.total_cost, cheapest_path_rows); else - cost_group(&sorted_p, parse, numGroupCols, dNumGroups, + cost_group(&sorted_p, root, numGroupCols, dNumGroups, sorted_p.startup_cost, sorted_p.total_cost, cheapest_path_rows); /* The Agg or Group node will preserve ordering */ if (sort_pathkeys && !pathkeys_contained_in(sort_pathkeys, current_pathkeys)) - cost_sort(&sorted_p, parse, sort_pathkeys, sorted_p.total_cost, + cost_sort(&sorted_p, root, sort_pathkeys, sorted_p.total_cost, dNumGroups, cheapest_path_width); /* @@ -1363,14 +1389,15 @@ choose_hashed_grouping(Query *parse, double tuple_fraction, * is marked hashjoinable. */ static bool -hash_safe_grouping(Query *parse) +hash_safe_grouping(PlannerInfo *root) { ListCell *gl; - foreach(gl, parse->groupClause) + foreach(gl, root->parse->groupClause) { GroupClause *grpcl = (GroupClause *) lfirst(gl); - TargetEntry *tle = get_sortgroupclause_tle(grpcl, parse->targetList); + TargetEntry *tle = get_sortgroupclause_tle(grpcl, + root->parse->targetList); Operator optup; bool oprcanhash; @@ -1417,7 +1444,6 @@ hash_safe_grouping(Query *parse) * need to force it to be evaluated, because all the Vars it contains * should be present in the output of query_planner anyway. * - * 'parse' is the query being processed. * 'tlist' is the query's target list. * 'groupColIdx' receives an array of column numbers for the GROUP BY * expressions (if there are any) in the subplan's target list. @@ -1428,11 +1454,12 @@ hash_safe_grouping(Query *parse) *--------------- */ static List * -make_subplanTargetList(Query *parse, +make_subplanTargetList(PlannerInfo *root, List *tlist, AttrNumber **groupColIdx, bool *need_tlist_eval) { + Query *parse = root->parse; List *sub_tlist; List *extravars; int numCols; @@ -1443,7 +1470,7 @@ make_subplanTargetList(Query *parse, * If we're not grouping or aggregating, there's nothing to do here; * query_planner should receive the unmodified target list. */ - if (!parse->hasAggs && !parse->groupClause && !parse->hasHavingQual) + if (!parse->hasAggs && !parse->groupClause && !root->hasHavingQual) { *need_tlist_eval = true; return tlist; @@ -1517,7 +1544,7 @@ make_subplanTargetList(Query *parse, * by that routine and re-locate the grouping vars in the real sub_tlist. */ static void -locate_grouping_columns(Query *parse, +locate_grouping_columns(PlannerInfo *root, List *tlist, List *sub_tlist, AttrNumber *groupColIdx) @@ -1528,14 +1555,14 @@ locate_grouping_columns(Query *parse, /* * No work unless grouping. */ - if (!parse->groupClause) + if (!root->parse->groupClause) { Assert(groupColIdx == NULL); return; } Assert(groupColIdx != NULL); - foreach(gl, parse->groupClause) + foreach(gl, root->parse->groupClause) { GroupClause *grpcl = (GroupClause *) lfirst(gl); Node *groupexpr = get_sortgroupclause_expr(grpcl, tlist); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 0865feae26..ec037db514 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.98 2005/04/25 01:30:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.99 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -292,7 +292,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) /* * Generate the plan for the subquery. */ - node->plan = plan = subquery_planner(subquery, tuple_fraction); + node->plan = plan = subquery_planner(subquery, tuple_fraction, NULL); node->plan_id = PlannerPlanId++; /* Assign unique ID to this * SubPlan */ @@ -417,10 +417,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) * top of the subplan, to reduce the cost of reading it * repeatedly. This is pointless for a direct-correlated subplan, * since we'd have to recompute its results each time anyway. For - * uncorrelated/undirect correlated subplans, we add MATERIAL if - * the subplan's top plan node is anything more complicated than a - * plain sequential scan, and we do it even for seqscan if the - * qual appears selective enough to eliminate many tuples. + * uncorrelated/undirect correlated subplans, we add MATERIAL unless + * the subplan's top plan node would materialize its output anyway. */ else if (node->parParam == NIL) { @@ -428,29 +426,9 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) switch (nodeTag(plan)) { - case T_SeqScan: - if (plan->initPlan) - use_material = true; - else - { - Selectivity qualsel; - - qualsel = clauselist_selectivity(subquery, - plan->qual, - 0, JOIN_INNER); - /* Is 10% selectivity a good threshold?? */ - use_material = qualsel < 0.10; - } - break; case T_Material: case T_FunctionScan: case T_Sort: - - /* - * Don't add another Material node if there's one - * already, nor if the top node is any other type that - * materializes its output anyway. - */ use_material = false; break; default: @@ -678,8 +656,9 @@ subplan_is_hashable(SubLink *slink, SubPlan *node) * its in_info_list. */ Node * -convert_IN_to_join(Query *parse, SubLink *sublink) +convert_IN_to_join(PlannerInfo *root, SubLink *sublink) { + Query *parse = root->parse; Query *subselect = (Query *) sublink->subselect; Relids left_varnos; int rtindex; @@ -746,7 +725,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink) ininfo = makeNode(InClauseInfo); ininfo->lefthand = left_varnos; ininfo->righthand = bms_make_singleton(rtindex); - parse->in_info_list = lcons(ininfo, parse->in_info_list); + root->in_info_list = lappend(root->in_info_list, ininfo); /* * Build the result qual expressions. As a side effect, @@ -1252,7 +1231,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context) * We assume the plan hasn't been put through SS_finalize_plan. */ Param * -SS_make_initplan_from_plan(Query *root, Plan *plan, +SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan, Oid resulttype, int32 resulttypmod) { List *saved_initplan = PlannerInitPlan; @@ -1271,7 +1250,7 @@ SS_make_initplan_from_plan(Query *root, Plan *plan, /* * Build extParam/allParam sets for plan nodes. */ - SS_finalize_plan(plan, root->rtable); + SS_finalize_plan(plan, root->parse->rtable); /* Return to outer subquery context */ PlannerQueryLevel--; @@ -1286,7 +1265,7 @@ SS_make_initplan_from_plan(Query *root, Plan *plan, node->plan_id = PlannerPlanId++; /* Assign unique ID to this * SubPlan */ - node->rtable = root->rtable; + node->rtable = root->parse->rtable; PlannerInitPlan = lappend(PlannerInitPlan, node); diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 67f4e823d8..ba758528c7 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.28 2005/06/04 19:19:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.29 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -50,7 +50,7 @@ static void resolvenew_in_jointree(Node *jtnode, int varno, static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode); static void reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_state *state, - Query *parse, + PlannerInfo *root, Relids nonnullable_rels); static Relids find_nonnullable_rels(Node *node, bool top_level); static void fix_in_clause_relids(List *in_info_list, int varno, @@ -79,7 +79,7 @@ static Node *find_jointree_node_for_rel(Node *jtnode, int relid); * Returns the possibly-modified version of the given qual-tree node. */ Node * -pull_up_IN_clauses(Query *parse, Node *node) +pull_up_IN_clauses(PlannerInfo *root, Node *node) { if (node == NULL) return NULL; @@ -89,7 +89,7 @@ pull_up_IN_clauses(Query *parse, Node *node) Node *subst; /* Is it a convertible IN clause? If not, return it as-is */ - subst = convert_IN_to_join(parse, sublink); + subst = convert_IN_to_join(root, sublink); if (subst == NULL) return node; return subst; @@ -104,8 +104,7 @@ pull_up_IN_clauses(Query *parse, Node *node) Node *oldclause = (Node *) lfirst(l); newclauses = lappend(newclauses, - pull_up_IN_clauses(parse, - oldclause)); + pull_up_IN_clauses(root, oldclause)); } return (Node *) make_andclause(newclauses); } @@ -132,13 +131,14 @@ pull_up_IN_clauses(Query *parse, Node *node) * copy of the tree; we have to invoke it just on the quals, instead. */ Node * -pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) +pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join) { if (jtnode == NULL) return NULL; if (IsA(jtnode, RangeTblRef)) { int varno = ((RangeTblRef *) jtnode)->rtindex; + Query *parse = root->parse; RangeTblEntry *rte = rt_fetch(varno, parse->rtable); Query *subquery = rte->subquery; @@ -160,6 +160,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) is_simple_subquery(subquery) && (!below_outer_join || has_nullable_targetlist(subquery))) { + PlannerInfo *subroot; int rtoffset; List *subtlist; ListCell *rt; @@ -173,12 +174,23 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) */ subquery = copyObject(subquery); + /* + * Create a PlannerInfo data structure for this subquery. + * + * NOTE: the next few steps should match the first processing + * in subquery_planner(). Can we refactor to avoid code + * duplication, or would that just make things uglier? + */ + subroot = makeNode(PlannerInfo); + subroot->parse = subquery; + /* * Pull up any IN clauses within the subquery's WHERE, so that * we don't leave unoptimized INs behind. */ + subroot->in_info_list = NIL; if (subquery->hasSubLinks) - subquery->jointree->quals = pull_up_IN_clauses(subquery, + subquery->jointree->quals = pull_up_IN_clauses(subroot, subquery->jointree->quals); /* @@ -191,7 +203,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) * clean slate for outer-join semantics. */ subquery->jointree = (FromExpr *) - pull_up_subqueries(subquery, (Node *) subquery->jointree, + pull_up_subqueries(subroot, (Node *) subquery->jointree, false); /* @@ -222,16 +234,19 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) /* * Adjust level-0 varnos in subquery so that we can append its - * rangetable to upper query's. + * rangetable to upper query's. We have to fix the subquery's + * in_info_list, as well. */ rtoffset = list_length(parse->rtable); OffsetVarNodes((Node *) subquery, rtoffset, 0); + OffsetVarNodes((Node *) subroot->in_info_list, rtoffset, 0); /* * Upper-level vars in subquery are now one level closer to * their parent than before. */ IncrementVarSublevelsUp((Node *) subquery, -1, 1); + IncrementVarSublevelsUp((Node *) subroot->in_info_list, -1, 1); /* * Replace all of the top query's references to the subquery's @@ -252,8 +267,8 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) ResolveNew(parse->havingQual, varno, 0, rte, subtlist, CMD_SELECT, 0); - parse->in_info_list = (List *) - ResolveNew((Node *) parse->in_info_list, + root->in_info_list = (List *) + ResolveNew((Node *) root->in_info_list, varno, 0, rte, subtlist, CMD_SELECT, 0); @@ -299,19 +314,19 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) * ResolveNew, but it would clutter that routine's API * unreasonably.) */ - if (parse->in_info_list) + if (root->in_info_list) { Relids subrelids; subrelids = get_relids_in_jointree((Node *) subquery->jointree); - fix_in_clause_relids(parse->in_info_list, varno, subrelids); + fix_in_clause_relids(root->in_info_list, varno, subrelids); } /* * And now append any subquery InClauseInfos to our list. */ - parse->in_info_list = list_concat(parse->in_info_list, - subquery->in_info_list); + root->in_info_list = list_concat(root->in_info_list, + subroot->in_info_list); /* * Miscellaneous housekeeping. @@ -332,7 +347,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) ListCell *l; foreach(l, f->fromlist) - lfirst(l) = pull_up_subqueries(parse, lfirst(l), + lfirst(l) = pull_up_subqueries(root, lfirst(l), below_outer_join); } else if (IsA(jtnode, JoinExpr)) @@ -343,27 +358,27 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join) switch (j->jointype) { case JOIN_INNER: - j->larg = pull_up_subqueries(parse, j->larg, + j->larg = pull_up_subqueries(root, j->larg, below_outer_join); - j->rarg = pull_up_subqueries(parse, j->rarg, + j->rarg = pull_up_subqueries(root, j->rarg, below_outer_join); break; case JOIN_LEFT: - j->larg = pull_up_subqueries(parse, j->larg, + j->larg = pull_up_subqueries(root, j->larg, below_outer_join); - j->rarg = pull_up_subqueries(parse, j->rarg, + j->rarg = pull_up_subqueries(root, j->rarg, true); break; case JOIN_FULL: - j->larg = pull_up_subqueries(parse, j->larg, + j->larg = pull_up_subqueries(root, j->larg, true); - j->rarg = pull_up_subqueries(parse, j->rarg, + j->rarg = pull_up_subqueries(root, j->rarg, true); break; case JOIN_RIGHT: - j->larg = pull_up_subqueries(parse, j->larg, + j->larg = pull_up_subqueries(root, j->larg, true); - j->rarg = pull_up_subqueries(parse, j->rarg, + j->rarg = pull_up_subqueries(root, j->rarg, below_outer_join); break; case JOIN_UNION: @@ -555,7 +570,7 @@ resolvenew_in_jointree(Node *jtnode, int varno, * alias-var expansion). */ void -reduce_outer_joins(Query *parse) +reduce_outer_joins(PlannerInfo *root) { reduce_outer_joins_state *state; @@ -569,13 +584,14 @@ reduce_outer_joins(Query *parse) * clause. The second pass examines qual clauses and changes join * types as it descends the tree. */ - state = reduce_outer_joins_pass1((Node *) parse->jointree); + state = reduce_outer_joins_pass1((Node *) root->parse->jointree); /* planner.c shouldn't have called me if no outer joins */ if (state == NULL || !state->contains_outer) elog(ERROR, "so where are the outer joins?"); - reduce_outer_joins_pass2((Node *) parse->jointree, state, parse, NULL); + reduce_outer_joins_pass2((Node *) root->parse->jointree, + state, root, NULL); } /* @@ -650,13 +666,13 @@ reduce_outer_joins_pass1(Node *jtnode) * * jtnode: current jointree node * state: state data collected by phase 1 for this node - * parse: toplevel Query + * root: toplevel planner state * nonnullable_rels: set of base relids forced non-null by upper quals */ static void reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_state *state, - Query *parse, + PlannerInfo *root, Relids nonnullable_rels) { /* @@ -685,7 +701,7 @@ reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_state *sub_state = lfirst(s); if (sub_state->contains_outer) - reduce_outer_joins_pass2(lfirst(l), sub_state, parse, + reduce_outer_joins_pass2(lfirst(l), sub_state, root, pass_nonnullable); } bms_free(pass_nonnullable); @@ -729,7 +745,7 @@ reduce_outer_joins_pass2(Node *jtnode, if (jointype != j->jointype) { /* apply the change to both jointree node and RTE */ - RangeTblEntry *rte = rt_fetch(rtindex, parse->rtable); + RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable); Assert(rte->rtekind == RTE_JOIN); Assert(rte->jointype == j->jointype); @@ -767,7 +783,7 @@ reduce_outer_joins_pass2(Node *jtnode, pass_nonnullable = local_nonnullable; else pass_nonnullable = nonnullable_rels; - reduce_outer_joins_pass2(j->larg, left_state, parse, + reduce_outer_joins_pass2(j->larg, left_state, root, pass_nonnullable); } if (right_state->contains_outer) @@ -776,7 +792,7 @@ reduce_outer_joins_pass2(Node *jtnode, pass_nonnullable = local_nonnullable; else pass_nonnullable = nonnullable_rels; - reduce_outer_joins_pass2(j->rarg, right_state, parse, + reduce_outer_joins_pass2(j->rarg, right_state, root, pass_nonnullable); } bms_free(local_nonnullable); @@ -909,7 +925,7 @@ find_nonnullable_rels(Node *node, bool top_level) * work reliably --- see comments for pull_up_subqueries(). */ Node * -simplify_jointree(Query *parse, Node *jtnode) +simplify_jointree(PlannerInfo *root, Node *jtnode) { if (jtnode == NULL) return NULL; @@ -931,7 +947,7 @@ simplify_jointree(Query *parse, Node *jtnode) children_remaining--; /* Recursively simplify this child... */ - child = simplify_jointree(parse, child); + child = simplify_jointree(root, child); /* Now, is it a FromExpr? */ if (child && IsA(child, FromExpr)) { @@ -972,8 +988,8 @@ simplify_jointree(Query *parse, Node *jtnode) JoinExpr *j = (JoinExpr *) jtnode; /* Recursively simplify the children... */ - j->larg = simplify_jointree(parse, j->larg); - j->rarg = simplify_jointree(parse, j->rarg); + j->larg = simplify_jointree(root, j->larg); + j->rarg = simplify_jointree(root, j->rarg); /* * If it is an outer join, we must not flatten it. An inner join @@ -1115,11 +1131,12 @@ get_relids_in_jointree(Node *jtnode) * since that may eliminate join nodes from the jointree. */ Relids -get_relids_for_join(Query *parse, int joinrelid) +get_relids_for_join(PlannerInfo *root, int joinrelid) { Node *jtnode; - jtnode = find_jointree_node_for_rel((Node *) parse->jointree, joinrelid); + jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree, + joinrelid); if (!jtnode) elog(ERROR, "could not find join node %d", joinrelid); return get_relids_in_jointree(jtnode); diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 22334e238f..fa56c5fc29 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.76 2005/05/23 03:01:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.77 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,8 +43,9 @@ static List *expand_targetlist(List *tlist, int command_type, * Returns the new targetlist. */ List * -preprocess_targetlist(Query *parse, List *tlist) +preprocess_targetlist(PlannerInfo *root, List *tlist) { + Query *parse = root->parse; int result_relation = parse->resultRelation; List *range_table = parse->rtable; CmdType command_type = parse->commandType; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 0f532a9945..e7aee1d52a 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.121 2005/05/22 22:30:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.122 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,15 +49,15 @@ typedef struct char *new_rel_name; } adjust_inherited_attrs_context; -static Plan *recurse_set_operations(Node *setOp, Query *parse, +static Plan *recurse_set_operations(Node *setOp, PlannerInfo *root, List *colTypes, bool junkOK, int flag, List *refnames_tlist, List **sortClauses); -static Plan *generate_union_plan(SetOperationStmt *op, Query *parse, +static Plan *generate_union_plan(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **sortClauses); -static Plan *generate_nonunion_plan(SetOperationStmt *op, Query *parse, +static Plan *generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **sortClauses); -static List *recurse_union_children(Node *setOp, Query *parse, +static List *recurse_union_children(Node *setOp, PlannerInfo *root, SetOperationStmt *top_union, List *refnames_tlist); static List *generate_setop_tlist(List *colTypes, int flag, @@ -82,15 +82,16 @@ static List *adjust_inherited_tlist(List *tlist, * Plans the queries for a tree of set operations (UNION/INTERSECT/EXCEPT) * * This routine only deals with the setOperations tree of the given query. - * Any top-level ORDER BY requested in parse->sortClause will be added + * Any top-level ORDER BY requested in root->parse->sortClause will be added * when we return to grouping_planner. * * *sortClauses is an output argument: it is set to a list of SortClauses * representing the result ordering of the topmost set operation. */ Plan * -plan_set_operations(Query *parse, List **sortClauses) +plan_set_operations(PlannerInfo *root, List **sortClauses) { + Query *parse = root->parse; SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations; Node *node; Query *leftmostQuery; @@ -123,7 +124,7 @@ plan_set_operations(Query *parse, List **sortClauses) * output from the top-level node, plus possibly resjunk working * columns (we can rely on upper-level nodes to deal with that). */ - return recurse_set_operations((Node *) topop, parse, + return recurse_set_operations((Node *) topop, root, topop->colTypes, true, -1, leftmostQuery->targetList, sortClauses); @@ -140,7 +141,7 @@ plan_set_operations(Query *parse, List **sortClauses) * *sortClauses: receives list of SortClauses for result plan, if any */ static Plan * -recurse_set_operations(Node *setOp, Query *parse, +recurse_set_operations(Node *setOp, PlannerInfo *root, List *colTypes, bool junkOK, int flag, List *refnames_tlist, List **sortClauses) @@ -148,7 +149,7 @@ recurse_set_operations(Node *setOp, Query *parse, if (IsA(setOp, RangeTblRef)) { RangeTblRef *rtr = (RangeTblRef *) setOp; - RangeTblEntry *rte = rt_fetch(rtr->rtindex, parse->rtable); + RangeTblEntry *rte = rt_fetch(rtr->rtindex, root->parse->rtable); Query *subquery = rte->subquery; Plan *subplan, *plan; @@ -158,7 +159,7 @@ recurse_set_operations(Node *setOp, Query *parse, /* * Generate plan for primitive subquery */ - subplan = subquery_planner(subquery, 0.0 /* default case */ ); + subplan = subquery_planner(subquery, 0.0 /* default case */, NULL); /* * Add a SubqueryScan with the caller-requested targetlist @@ -188,10 +189,10 @@ recurse_set_operations(Node *setOp, Query *parse, /* UNIONs are much different from INTERSECT/EXCEPT */ if (op->op == SETOP_UNION) - plan = generate_union_plan(op, parse, refnames_tlist, + plan = generate_union_plan(op, root, refnames_tlist, sortClauses); else - plan = generate_nonunion_plan(op, parse, refnames_tlist, + plan = generate_nonunion_plan(op, root, refnames_tlist, sortClauses); /* @@ -233,7 +234,7 @@ recurse_set_operations(Node *setOp, Query *parse, * Generate plan for a UNION or UNION ALL node */ static Plan * -generate_union_plan(SetOperationStmt *op, Query *parse, +generate_union_plan(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **sortClauses) { @@ -247,9 +248,9 @@ generate_union_plan(SetOperationStmt *op, Query *parse, * generate only one Append and Sort for the lot. Recurse to find * such nodes and compute their children's plans. */ - planlist = list_concat(recurse_union_children(op->larg, parse, + planlist = list_concat(recurse_union_children(op->larg, root, op, refnames_tlist), - recurse_union_children(op->rarg, parse, + recurse_union_children(op->rarg, root, op, refnames_tlist)); /* @@ -278,7 +279,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse, sortList = addAllTargetsToSortList(NULL, NIL, tlist, false); if (sortList) { - plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan); + plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan); plan = (Plan *) make_unique(plan, sortList); } *sortClauses = sortList; @@ -293,7 +294,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse, * Generate plan for an INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL node */ static Plan * -generate_nonunion_plan(SetOperationStmt *op, Query *parse, +generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **sortClauses) { @@ -307,11 +308,11 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, SetOpCmd cmd; /* Recurse on children, ensuring their outputs are marked */ - lplan = recurse_set_operations(op->larg, parse, + lplan = recurse_set_operations(op->larg, root, op->colTypes, false, 0, refnames_tlist, &child_sortclauses); - rplan = recurse_set_operations(op->rarg, parse, + rplan = recurse_set_operations(op->rarg, root, op->colTypes, false, 1, refnames_tlist, &child_sortclauses); @@ -346,7 +347,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, return plan; } - plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan); + plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan); switch (op->op) { case SETOP_INTERSECT: @@ -375,7 +376,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, * output rows will be lost anyway. */ static List * -recurse_union_children(Node *setOp, Query *parse, +recurse_union_children(Node *setOp, PlannerInfo *root, SetOperationStmt *top_union, List *refnames_tlist) { @@ -390,10 +391,10 @@ recurse_union_children(Node *setOp, Query *parse, equal(op->colTypes, top_union->colTypes)) { /* Same UNION, so fold children into parent's subplan list */ - return list_concat(recurse_union_children(op->larg, parse, + return list_concat(recurse_union_children(op->larg, root, top_union, refnames_tlist), - recurse_union_children(op->rarg, parse, + recurse_union_children(op->rarg, root, top_union, refnames_tlist)); } @@ -409,7 +410,7 @@ recurse_union_children(Node *setOp, Query *parse, * we have an EXCEPT or INTERSECT as child, else there won't be * resjunk anyway. */ - return list_make1(recurse_set_operations(setOp, parse, + return list_make1(recurse_set_operations(setOp, root, top_union->colTypes, false, -1, refnames_tlist, &child_sortclauses)); @@ -724,8 +725,9 @@ find_all_inheritors(Oid parentrel) * trying to avoid. */ List * -expand_inherited_rtentry(Query *parse, Index rti) +expand_inherited_rtentry(PlannerInfo *root, Index rti) { + Query *parse = root->parse; RangeTblEntry *rte = rt_fetch(rti, parse->rtable); Oid parentOID; List *inhOIDs; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 429e5d2495..5663cce6e8 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.197 2005/05/22 22:30:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.198 2005/06/05 22:32:56 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -3040,8 +3040,6 @@ query_tree_walker(Query *query, return true; if (walker(query->limitCount, context)) return true; - if (walker(query->in_info_list, context)) - return true; if (range_table_walker(query->rtable, walker, context, flags)) return true; return false; @@ -3564,7 +3562,6 @@ query_tree_mutator(Query *query, MUTATE(query->havingQual, query->havingQual, Node *); MUTATE(query->limitOffset, query->limitOffset, Node *); MUTATE(query->limitCount, query->limitCount, Node *); - MUTATE(query->in_info_list, query->in_info_list, List *); query->rtable = range_table_mutator(query->rtable, mutator, context, flags); return query; diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c index 8a19892750..b49ead1316 100644 --- a/src/backend/optimizer/util/joininfo.c +++ b/src/backend/optimizer/util/joininfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.41 2004/12/31 22:00:23 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.42 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,7 +82,7 @@ make_joininfo_node(RelOptInfo *this_rel, Relids join_relids) * (there must be more than one) */ void -add_join_clause_to_rels(Query *root, +add_join_clause_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids) { @@ -131,7 +131,7 @@ add_join_clause_to_rels(Query *root, * (there must be more than one) */ void -remove_join_clause_from_rels(Query *root, +remove_join_clause_from_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids) { diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index cf5438f06c..4c52561521 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.121 2005/06/03 19:00:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.122 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -415,7 +415,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * pathnode. */ Path * -create_seqscan_path(Query *root, RelOptInfo *rel) +create_seqscan_path(PlannerInfo *root, RelOptInfo *rel) { Path *pathnode = makeNode(Path); @@ -445,7 +445,7 @@ create_seqscan_path(Query *root, RelOptInfo *rel) * Returns the new path node. */ IndexPath * -create_index_path(Query *root, +create_index_path(PlannerInfo *root, IndexOptInfo *index, List *clause_groups, List *pathkeys, @@ -537,7 +537,7 @@ create_index_path(Query *root, * 'bitmapqual' is a tree of IndexPath, BitmapAndPath, and BitmapOrPath nodes. */ BitmapHeapPath * -create_bitmap_heap_path(Query *root, +create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, bool isjoininner) @@ -590,7 +590,7 @@ create_bitmap_heap_path(Query *root, * Creates a path node representing a BitmapAnd. */ BitmapAndPath * -create_bitmap_and_path(Query *root, +create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals) { @@ -613,7 +613,7 @@ create_bitmap_and_path(Query *root, * Creates a path node representing a BitmapOr. */ BitmapOrPath * -create_bitmap_or_path(Query *root, +create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals) { @@ -637,7 +637,7 @@ create_bitmap_or_path(Query *root, * pathnode. */ TidPath * -create_tidscan_path(Query *root, RelOptInfo *rel, List *tideval) +create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tideval) { TidPath *pathnode = makeNode(TidPath); @@ -759,7 +759,7 @@ create_material_path(RelOptInfo *rel, Path *subpath) * for the rel). So we cache the result. */ UniquePath * -create_unique_path(Query *root, RelOptInfo *rel, Path *subpath) +create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath) { UniquePath *pathnode; Path sort_path; /* dummy for result of cost_sort */ @@ -805,7 +805,7 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath) */ if (rel->rtekind == RTE_SUBQUERY) { - RangeTblEntry *rte = rt_fetch(rel->relid, root->rtable); + RangeTblEntry *rte = rt_fetch(rel->relid, root->parse->rtable); if (is_distinct_query(rte->subquery)) { @@ -1029,7 +1029,7 @@ create_subqueryscan_path(RelOptInfo *rel, List *pathkeys) * returning the pathnode. */ Path * -create_functionscan_path(Query *root, RelOptInfo *rel) +create_functionscan_path(PlannerInfo *root, RelOptInfo *rel) { Path *pathnode = makeNode(Path); @@ -1057,7 +1057,7 @@ create_functionscan_path(Query *root, RelOptInfo *rel) * Returns the resulting path node. */ NestPath * -create_nestloop_path(Query *root, +create_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, @@ -1097,7 +1097,7 @@ create_nestloop_path(Query *root, * 'innersortkeys' are the sort varkeys for the inner relation */ MergePath * -create_mergejoin_path(Query *root, +create_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, @@ -1166,7 +1166,7 @@ create_mergejoin_path(Query *root, * (this should be a subset of the restrict_clauses list) */ HashPath * -create_hashjoin_path(Query *root, +create_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index a86bdbfb61..a8dcdae9a2 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.110 2005/06/04 19:19:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.111 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -379,11 +379,11 @@ estimate_rel_size(Relation rel, int32 *attr_widths, * nodes. */ List * -build_physical_tlist(Query *root, RelOptInfo *rel) +build_physical_tlist(PlannerInfo *root, RelOptInfo *rel) { List *tlist = NIL; Index varno = rel->relid; - RangeTblEntry *rte = rt_fetch(varno, root->rtable); + RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable); Relation relation; Query *subquery; Var *var; @@ -494,7 +494,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel) * See clause_selectivity() for the meaning of the additional parameters. */ Selectivity -restriction_selectivity(Query *root, +restriction_selectivity(PlannerInfo *root, Oid operator, List *args, int varRelid) @@ -529,7 +529,7 @@ restriction_selectivity(Query *root, * operator relation, by calling the function manager. */ Selectivity -join_selectivity(Query *root, +join_selectivity(PlannerInfo *root, Oid operator, List *args, JoinType jointype) diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index f679768cfe..5a39bf3f05 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.66 2005/05/23 03:01:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.67 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,10 +23,10 @@ #include "parser/parsetree.h" -static RelOptInfo *make_reloptinfo(Query *root, int relid, +static RelOptInfo *make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind); -static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel); -static List *build_joinrel_restrictlist(Query *root, +static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel); +static List *build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, @@ -46,7 +46,7 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel, * base_rel_list. */ void -build_base_rel(Query *root, int relid) +build_base_rel(PlannerInfo *root, int relid) { ListCell *l; RelOptInfo *rel; @@ -81,7 +81,7 @@ build_base_rel(Query *root, int relid) * base relations except that they live in a different list. */ RelOptInfo * -build_other_rel(Query *root, int relid) +build_other_rel(PlannerInfo *root, int relid) { ListCell *l; RelOptInfo *rel; @@ -119,10 +119,10 @@ build_other_rel(Query *root, int relid) * Common code for build_base_rel and build_other_rel. */ static RelOptInfo * -make_reloptinfo(Query *root, int relid, RelOptKind reloptkind) +make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind) { RelOptInfo *rel = makeNode(RelOptInfo); - RangeTblEntry *rte = rt_fetch(relid, root->rtable); + RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable); rel->reloptkind = reloptkind; rel->relids = bms_make_singleton(relid); @@ -181,7 +181,7 @@ make_reloptinfo(Query *root, int relid, RelOptKind reloptkind) * (since we'd have no idea which list to add it to). */ RelOptInfo * -find_base_rel(Query *root, int relid) +find_base_rel(PlannerInfo *root, int relid) { ListCell *l; RelOptInfo *rel; @@ -211,7 +211,7 @@ find_base_rel(Query *root, int relid) * or NULL if none exists. This is for join relations. */ RelOptInfo * -find_join_rel(Query *root, Relids relids) +find_join_rel(PlannerInfo *root, Relids relids) { ListCell *l; @@ -243,7 +243,7 @@ find_join_rel(Query *root, Relids relids) * duplicated calculation of the restrictlist... */ RelOptInfo * -build_join_rel(Query *root, +build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, @@ -356,7 +356,7 @@ build_join_rel(Query *root, * of data that was cached at the baserel level by set_rel_width(). */ static void -build_joinrel_tlist(Query *root, RelOptInfo *joinrel) +build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel) { Relids relids = joinrel->relids; ListCell *rels; @@ -433,7 +433,7 @@ build_joinrel_tlist(Query *root, RelOptInfo *joinrel) * the original nodes in the lists made for the join relation. */ static List * -build_joinrel_restrictlist(Query *root, +build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index e19a308cdf..460ccc9546 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.35 2005/04/25 02:14:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.36 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,7 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause, static Expr *make_sub_restrictinfos(Expr *clause, bool is_pushed_down, bool valid_everywhere); -static RestrictInfo *join_clause_is_redundant(Query *root, +static RestrictInfo *join_clause_is_redundant(PlannerInfo *root, RestrictInfo *rinfo, List *reference_list, bool isouterjoin); @@ -354,7 +354,7 @@ get_actual_join_clauses(List *restrictinfo_list, * as were in the input. */ List * -remove_redundant_join_clauses(Query *root, List *restrictinfo_list, +remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list, bool isouterjoin) { List *result = NIL; @@ -415,7 +415,7 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list, * for local redundancies, so we don't check again. */ List * -select_nonredundant_join_clauses(Query *root, +select_nonredundant_join_clauses(PlannerInfo *root, List *restrictinfo_list, List *reference_list, bool isouterjoin) @@ -467,7 +467,7 @@ select_nonredundant_join_clauses(Query *root, * joined rows after addition of null fill rows, and the other doesn't. */ static RestrictInfo * -join_clause_is_redundant(Query *root, +join_clause_is_redundant(PlannerInfo *root, RestrictInfo *rinfo, List *reference_list, bool isouterjoin) diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index a95f7dcd76..abd01ca157 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.64 2005/06/03 23:05:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.65 2005/06/05 22:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,7 @@ typedef struct typedef struct { - Query *root; + PlannerInfo *root; int sublevels_up; } flatten_join_alias_vars_context; @@ -66,7 +66,7 @@ static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context); static Node *flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context); -static Relids alias_relid_set(Query *root, Relids relids); +static Relids alias_relid_set(PlannerInfo *root, Relids relids); /* @@ -482,7 +482,7 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) * to be applied directly to a Query node. */ Node * -flatten_join_alias_vars(Query *root, Node *node) +flatten_join_alias_vars(PlannerInfo *root, Node *node) { flatten_join_alias_vars_context context; @@ -507,7 +507,7 @@ flatten_join_alias_vars_mutator(Node *node, /* No change unless Var belongs to a JOIN of the target level */ if (var->varlevelsup != context->sublevels_up) return node; /* no need to copy, really */ - rte = rt_fetch(var->varno, context->root->rtable); + rte = rt_fetch(var->varno, context->root->parse->rtable); if (rte->rtekind != RTE_JOIN) return node; if (var->varattno == InvalidAttrNumber) @@ -608,7 +608,7 @@ flatten_join_alias_vars_mutator(Node *node, * underlying base relids */ static Relids -alias_relid_set(Query *root, Relids relids) +alias_relid_set(PlannerInfo *root, Relids relids) { Relids result = NULL; Relids tmprelids; @@ -617,7 +617,7 @@ alias_relid_set(Query *root, Relids relids) tmprelids = bms_copy(relids); while ((rtindex = bms_first_member(tmprelids)) >= 0) { - RangeTblEntry *rte = rt_fetch(rtindex, root->rtable); + RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable); if (rte->rtekind == RTE_JOIN) result = bms_join(result, get_relids_for_join(root, rtindex)); diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 18a42c5742..799bacd233 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.68 2005/03/29 00:17:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.69 2005/06/05 22:32:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,6 +101,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry) bool have_non_var_grouping; ListCell *l; bool hasJoinRTEs; + PlannerInfo *root; Node *clause; /* This should only be called if we found aggregates or grouping */ @@ -162,9 +163,22 @@ parseCheckAggregates(ParseState *pstate, Query *qry) } } + /* + * We use the planner's flatten_join_alias_vars routine to do the + * flattening; it wants a PlannerInfo root node, which fortunately + * can be mostly dummy. + */ if (hasJoinRTEs) - groupClauses = (List *) flatten_join_alias_vars(qry, + { + root = makeNode(PlannerInfo); + root->parse = qry; + root->hasJoinRTEs = true; + + groupClauses = (List *) flatten_join_alias_vars(root, (Node *) groupClauses); + } + else + root = NULL; /* keep compiler quiet */ /* * Detect whether any of the grouping expressions aren't simple Vars; @@ -186,13 +200,13 @@ parseCheckAggregates(ParseState *pstate, Query *qry) */ clause = (Node *) qry->targetList; if (hasJoinRTEs) - clause = flatten_join_alias_vars(qry, clause); + clause = flatten_join_alias_vars(root, clause); check_ungrouped_columns(clause, pstate, groupClauses, have_non_var_grouping); clause = (Node *) qry->havingQual; if (hasJoinRTEs) - clause = flatten_join_alias_vars(qry, clause); + clause = flatten_join_alias_vars(root, clause); check_ungrouped_columns(clause, pstate, groupClauses, have_non_var_grouping); } diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index d2b22d30eb..12157fb4d9 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.179 2005/06/01 17:05:11 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.180 2005/06/05 22:32:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,7 +38,7 @@ * * The call convention for a restriction estimator (oprrest function) is * - * Selectivity oprrest (Query *root, + * Selectivity oprrest (PlannerInfo *root, * Oid operator, * List *args, * int varRelid); @@ -59,7 +59,7 @@ * except that varRelid is not needed, and instead the join type is * supplied: * - * Selectivity oprjoin (Query *root, + * Selectivity oprjoin (PlannerInfo *root, * Oid operator, * List *args, * JoinType jointype); @@ -152,18 +152,18 @@ static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen, int rangelo, int rangehi); static unsigned char *convert_string_datum(Datum value, Oid typid); static double convert_timevalue_to_scalar(Datum value, Oid typid); -static bool get_restriction_variable(Query *root, List *args, int varRelid, +static bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft); -static void get_join_variables(Query *root, List *args, +static void get_join_variables(PlannerInfo *root, List *args, VariableStatData *vardata1, VariableStatData *vardata2); -static void examine_variable(Query *root, Node *node, int varRelid, +static void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata); static double get_variable_numdistinct(VariableStatData *vardata); -static bool get_variable_maximum(Query *root, VariableStatData *vardata, +static bool get_variable_maximum(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Datum *max); -static Selectivity prefix_selectivity(Query *root, Node *variable, +static Selectivity prefix_selectivity(PlannerInfo *root, Node *variable, Oid opclass, Const *prefix); static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype); static Datum string_to_datum(const char *str, Oid datatype); @@ -182,7 +182,7 @@ static Const *string_to_bytea_const(const char *str, size_t str_len); Datum eqsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); int varRelid = PG_GETARG_INT32(3); @@ -377,7 +377,7 @@ eqsel(PG_FUNCTION_ARGS) Datum neqsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); int varRelid = PG_GETARG_INT32(3); @@ -420,7 +420,7 @@ neqsel(PG_FUNCTION_ARGS) * it will return a default estimate. */ static double -scalarineqsel(Query *root, Oid operator, bool isgt, +scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, VariableStatData *vardata, Datum constval, Oid consttype) { Form_pg_statistic stats; @@ -652,7 +652,7 @@ scalarineqsel(Query *root, Oid operator, bool isgt, Datum scalarltsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); int varRelid = PG_GETARG_INT32(3); @@ -728,7 +728,7 @@ scalarltsel(PG_FUNCTION_ARGS) Datum scalargtsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); int varRelid = PG_GETARG_INT32(3); @@ -804,7 +804,7 @@ scalargtsel(PG_FUNCTION_ARGS) static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); #ifdef NOT_USED Oid operator = PG_GETARG_OID(1); @@ -1073,7 +1073,7 @@ icnlikesel(PG_FUNCTION_ARGS) * booltestsel - Selectivity of BooleanTest Node. */ Selectivity -booltestsel(Query *root, BoolTestType booltesttype, Node *arg, +booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype) { VariableStatData vardata; @@ -1238,7 +1238,8 @@ booltestsel(Query *root, BoolTestType booltesttype, Node *arg, * nulltestsel - Selectivity of NullTest Node. */ Selectivity -nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid) +nulltestsel(PlannerInfo *root, NullTestType nulltesttype, + Node *arg, int varRelid) { VariableStatData vardata; double selec; @@ -1310,7 +1311,7 @@ nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid) Datum eqjoinsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); JoinType jointype = (JoinType) PG_GETARG_INT16(3); @@ -1570,7 +1571,7 @@ eqjoinsel(PG_FUNCTION_ARGS) Datum neqjoinsel(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); JoinType jointype = (JoinType) PG_GETARG_INT16(3); @@ -1720,7 +1721,7 @@ icnlikejoinsel(PG_FUNCTION_ARGS) * variable. */ void -mergejoinscansel(Query *root, Node *clause, +mergejoinscansel(PlannerInfo *root, Node *clause, Selectivity *leftscan, Selectivity *rightscan) { @@ -1841,7 +1842,7 @@ typedef struct } GroupVarInfo; static List * -add_unique_group_var(Query *root, List *varinfos, +add_unique_group_var(PlannerInfo *root, List *varinfos, Node *var, VariableStatData *vardata) { GroupVarInfo *varinfo; @@ -1953,7 +1954,7 @@ add_unique_group_var(Query *root, List *varinfos, * do better). */ double -estimate_num_groups(Query *root, List *groupExprs, double input_rows) +estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows) { List *varinfos = NIL; double numdistinct; @@ -2151,7 +2152,7 @@ estimate_num_groups(Query *root, List *groupExprs, double input_rows) * inner rel is well-dispersed (or the alternatives seem much worse). */ Selectivity -estimate_hash_bucketsize(Query *root, Node *hashkey, double nbuckets) +estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey, double nbuckets) { VariableStatData vardata; double estfract, @@ -2840,7 +2841,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid) * and also indicate which side it was on and the other argument. * * Inputs: - * root: the Query + * root: the planner info * args: clause argument list * varRelid: see specs for restriction selectivity functions * @@ -2855,7 +2856,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid) * callers are expecting that the other side will act like a pseudoconstant. */ static bool -get_restriction_variable(Query *root, List *args, int varRelid, +get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft) { @@ -2909,7 +2910,7 @@ get_restriction_variable(Query *root, List *args, int varRelid, * Apply examine_variable() to each side of a join clause. */ static void -get_join_variables(Query *root, List *args, +get_join_variables(PlannerInfo *root, List *args, VariableStatData *vardata1, VariableStatData *vardata2) { Node *left, @@ -2931,7 +2932,7 @@ get_join_variables(Query *root, List *args, * Fill in a VariableStatData struct to describe the expression. * * Inputs: - * root: the Query + * root: the planner info * node: the expression tree to examine * varRelid: see specs for restriction selectivity functions * @@ -2952,7 +2953,7 @@ get_join_variables(Query *root, List *args, * Caller is responsible for doing ReleaseVariableStats() before exiting. */ static void -examine_variable(Query *root, Node *node, int varRelid, +examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata) { Node *basenode; @@ -2985,7 +2986,7 @@ examine_variable(Query *root, Node *node, int varRelid, vardata->atttype = var->vartype; vardata->atttypmod = var->vartypmod; - relid = getrelid(var->varno, root->rtable); + relid = getrelid(var->varno, root->parse->rtable); if (OidIsValid(relid)) { @@ -3250,7 +3251,7 @@ get_variable_numdistinct(VariableStatData *vardata) * minimum instead of the maximum, just pass the ">" operator instead.) */ static bool -get_variable_maximum(Query *root, VariableStatData *vardata, +get_variable_maximum(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Datum *max) { Datum tmax = 0; @@ -3696,7 +3697,7 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype, * more useful to use the upper-bound code than not. */ static Selectivity -prefix_selectivity(Query *root, Node *variable, +prefix_selectivity(PlannerInfo *root, Node *variable, Oid opclass, Const *prefixcon) { Selectivity prefixsel; @@ -4198,7 +4199,7 @@ string_to_bytea_const(const char *str, size_t str_len) */ static void -genericcostestimate(Query *root, +genericcostestimate(PlannerInfo *root, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, Cost *indexTotalCost, @@ -4327,7 +4328,7 @@ genericcostestimate(Query *root, Datum btcostestimate(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); List *indexQuals = (List *) PG_GETARG_POINTER(2); Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); @@ -4354,7 +4355,7 @@ btcostestimate(PG_FUNCTION_ARGS) if (index->indexkeys[0] != 0) { /* Simple variable --- look to stats for the underlying table */ - relid = getrelid(index->rel->relid, root->rtable); + relid = getrelid(index->rel->relid, root->parse->rtable); Assert(relid != InvalidOid); colnum = index->indexkeys[0]; } @@ -4406,7 +4407,7 @@ btcostestimate(PG_FUNCTION_ARGS) Datum rtcostestimate(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); List *indexQuals = (List *) PG_GETARG_POINTER(2); Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); @@ -4424,7 +4425,7 @@ rtcostestimate(PG_FUNCTION_ARGS) Datum hashcostestimate(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); List *indexQuals = (List *) PG_GETARG_POINTER(2); Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); @@ -4442,7 +4443,7 @@ hashcostestimate(PG_FUNCTION_ARGS) Datum gistcostestimate(PG_FUNCTION_ARGS) { - Query *root = (Query *) PG_GETARG_POINTER(0); + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); List *indexQuals = (List *) PG_GETARG_POINTER(2); Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index d69734f95e..326e929d76 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.168 2005/04/21 19:18:13 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.169 2005/06/05 22:32:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -165,7 +165,8 @@ typedef enum NodeTag /* * TAGS FOR PLANNER NODES (relation.h) */ - T_RelOptInfo = 500, + T_PlannerInfo = 500, + T_RelOptInfo, T_IndexOptInfo, T_Path, T_IndexPath, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 9a525eb1de..04b32082eb 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.280 2005/06/05 00:38:10 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.281 2005/06/05 22:32:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -62,8 +62,9 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */ * Query - * all statements are turned into a Query tree (via transformStmt) * for further processing by the optimizer - * utility statements (i.e. non-optimizable statements) - * have the *utilityStmt field set. + * + * utility statements (i.e. non-optimizable statements) have the + * utilityStmt field set, and the Query itself is mostly dummy. */ typedef struct Query { @@ -121,17 +122,6 @@ typedef struct Query * ought to go in some sort of TopPlan plan node, not in the Query. */ List *resultRelations; /* integer list of RT indexes, or NIL */ - - /* internal to planner */ - List *base_rel_list; /* list of base-relation RelOptInfos */ - List *other_rel_list; /* list of other 1-relation RelOptInfos */ - List *join_rel_list; /* list of join-relation RelOptInfos */ - List *equi_key_list; /* list of lists of equijoined - * PathKeyItems */ - List *in_info_list; /* list of InClauseInfos */ - List *query_pathkeys; /* desired pathkeys for query_planner() */ - bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */ - bool hasHavingQual; /* true if havingQual was non-null */ } Query; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 4618cf3a07..4cbf285029 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.109 2005/04/25 01:30:14 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.110 2005/06/05 22:32:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,6 +46,40 @@ typedef struct QualCost Cost per_tuple; /* per-evaluation cost */ } QualCost; + +/*---------- + * PlannerInfo + * Per-query information for planning/optimization + * + * This struct is conventionally called "root" in all the planner routines. + * It holds links to all of the planner's working state, in addition to the + * original Query. Note that at present the planner extensively manipulates + * the passed-in Query data structure; someday that should stop. + *---------- + */ +typedef struct PlannerInfo +{ + NodeTag type; + + Query *parse; /* the Query being planned */ + + List *base_rel_list; /* list of base-relation RelOptInfos */ + List *other_rel_list; /* list of other 1-relation RelOptInfos */ + List *join_rel_list; /* list of join-relation RelOptInfos */ + + List *equi_key_list; /* list of lists of equijoined + * PathKeyItems */ + + List *in_info_list; /* list of InClauseInfos */ + + List *query_pathkeys; /* desired pathkeys for query_planner(), + * and actual pathkeys afterwards */ + + bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */ + bool hasHavingQual; /* true if havingQual was non-null */ +} PlannerInfo; + + /*---------- * RelOptInfo * Per-relation information for planning/optimization @@ -55,7 +89,7 @@ typedef struct QualCost * In either case it is uniquely identified by an RT index. A "joinrel" * is the joining of two or more base rels. A joinrel is identified by * the set of RT indexes for its component baserels. We create RelOptInfo - * nodes for each baserel and joinrel, and store them in the Query's + * nodes for each baserel and joinrel, and store them in the PlannerInfo's * base_rel_list and join_rel_list respectively. * * Note that there is only one joinrel for any given set of component @@ -778,7 +812,7 @@ typedef struct InnerIndexscanInfo * When we convert top-level IN quals into join operations, we must restrict * the order of joining and use special join methods at some join points. * We record information about each such IN clause in an InClauseInfo struct. - * These structs are kept in the Query node's in_info_list. + * These structs are kept in the PlannerInfo node's in_info_list. */ typedef struct InClauseInfo diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 0f9e56880d..5b6d282425 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.67 2005/04/22 21:58:32 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.68 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,53 +51,53 @@ extern bool enable_mergejoin; extern bool enable_hashjoin; extern double clamp_row_est(double nrows); -extern void cost_seqscan(Path *path, Query *root, RelOptInfo *baserel); -extern void cost_index(IndexPath *path, Query *root, IndexOptInfo *index, +extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel); +extern void cost_index(IndexPath *path, PlannerInfo *root, IndexOptInfo *index, List *indexQuals, bool is_injoin); -extern void cost_bitmap_heap_scan(Path *path, Query *root, RelOptInfo *baserel, +extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual, bool is_injoin); -extern void cost_bitmap_and_node(BitmapAndPath *path, Query *root); -extern void cost_bitmap_or_node(BitmapOrPath *path, Query *root); +extern void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root); +extern void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root); extern void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec); -extern void cost_tidscan(Path *path, Query *root, +extern void cost_tidscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tideval); extern void cost_subqueryscan(Path *path, RelOptInfo *baserel); -extern void cost_functionscan(Path *path, Query *root, +extern void cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel); -extern void cost_sort(Path *path, Query *root, +extern void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width); extern void cost_material(Path *path, Cost input_cost, double tuples, int width); -extern void cost_agg(Path *path, Query *root, +extern void cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, int numAggs, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, double input_tuples); -extern void cost_group(Path *path, Query *root, +extern void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, double input_tuples); -extern void cost_nestloop(NestPath *path, Query *root); -extern void cost_mergejoin(MergePath *path, Query *root); -extern void cost_hashjoin(HashPath *path, Query *root); +extern void cost_nestloop(NestPath *path, PlannerInfo *root); +extern void cost_mergejoin(MergePath *path, PlannerInfo *root); +extern void cost_hashjoin(HashPath *path, PlannerInfo *root); extern void cost_qual_eval(QualCost *cost, List *quals); -extern void set_baserel_size_estimates(Query *root, RelOptInfo *rel); -extern void set_joinrel_size_estimates(Query *root, RelOptInfo *rel, +extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel); +extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List *restrictlist); -extern void set_function_size_estimates(Query *root, RelOptInfo *rel); +extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel); /* * prototypes for clausesel.c * routines to compute clause selectivities */ -extern Selectivity clauselist_selectivity(Query *root, +extern Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype); -extern Selectivity clause_selectivity(Query *root, +extern Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype); diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h index 53d0644c38..b67fc1aa49 100644 --- a/src/include/optimizer/geqo.h +++ b/src/include/optimizer/geqo.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.38 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.39 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -72,13 +72,14 @@ extern double Geqo_selection_bias; */ typedef struct { - Query *root; /* the query we are planning */ + PlannerInfo *root; /* the query we are planning */ List *initial_rels; /* the base relations */ } GeqoEvalData; /* routines in geqo_main.c */ -extern RelOptInfo *geqo(Query *root, int number_of_rels, List *initial_rels); +extern RelOptInfo *geqo(PlannerInfo *root, + int number_of_rels, List *initial_rels); /* routines in geqo_eval.c */ extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata); diff --git a/src/include/optimizer/joininfo.h b/src/include/optimizer/joininfo.h index fb1217cf6a..b0f0f56fd9 100644 --- a/src/include/optimizer/joininfo.h +++ b/src/include/optimizer/joininfo.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.28 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.29 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,10 +20,10 @@ extern JoinInfo *find_joininfo_node(RelOptInfo *this_rel, Relids join_relids); extern JoinInfo *make_joininfo_node(RelOptInfo *this_rel, Relids join_relids); -extern void add_join_clause_to_rels(Query *root, +extern void add_join_clause_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids); -extern void remove_join_clause_from_rels(Query *root, +extern void remove_join_clause_from_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids); diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index f5c11ff58e..009ada29da 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.60 2005/04/22 21:58:32 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.61 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,35 +27,35 @@ extern int compare_fractional_path_costs(Path *path1, Path *path2, extern void set_cheapest(RelOptInfo *parent_rel); extern void add_path(RelOptInfo *parent_rel, Path *new_path); -extern Path *create_seqscan_path(Query *root, RelOptInfo *rel); -extern IndexPath *create_index_path(Query *root, +extern Path *create_seqscan_path(PlannerInfo *root, RelOptInfo *rel); +extern IndexPath *create_index_path(PlannerInfo *root, IndexOptInfo *index, List *clause_groups, List *pathkeys, ScanDirection indexscandir, bool isjoininner); -extern BitmapHeapPath *create_bitmap_heap_path(Query *root, +extern BitmapHeapPath *create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, bool isjoininner); -extern BitmapAndPath *create_bitmap_and_path(Query *root, +extern BitmapAndPath *create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals); -extern BitmapOrPath *create_bitmap_or_path(Query *root, +extern BitmapOrPath *create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals); -extern TidPath *create_tidscan_path(Query *root, RelOptInfo *rel, +extern TidPath *create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tideval); extern AppendPath *create_append_path(RelOptInfo *rel, List *subpaths); extern ResultPath *create_result_path(RelOptInfo *rel, Path *subpath, List *constantqual); extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath); -extern UniquePath *create_unique_path(Query *root, RelOptInfo *rel, +extern UniquePath *create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath); extern Path *create_subqueryscan_path(RelOptInfo *rel, List *pathkeys); -extern Path *create_functionscan_path(Query *root, RelOptInfo *rel); +extern Path *create_functionscan_path(PlannerInfo *root, RelOptInfo *rel); -extern NestPath *create_nestloop_path(Query *root, +extern NestPath *create_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, @@ -63,7 +63,7 @@ extern NestPath *create_nestloop_path(Query *root, List *restrict_clauses, List *pathkeys); -extern MergePath *create_mergejoin_path(Query *root, +extern MergePath *create_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, @@ -74,7 +74,7 @@ extern MergePath *create_mergejoin_path(Query *root, List *outersortkeys, List *innersortkeys); -extern HashPath *create_hashjoin_path(Query *root, +extern HashPath *create_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, Path *outer_path, @@ -85,11 +85,11 @@ extern HashPath *create_hashjoin_path(Query *root, /* * prototypes for relnode.c */ -extern void build_base_rel(Query *root, int relid); -extern RelOptInfo *build_other_rel(Query *root, int relid); -extern RelOptInfo *find_base_rel(Query *root, int relid); -extern RelOptInfo *find_join_rel(Query *root, Relids relids); -extern RelOptInfo *build_join_rel(Query *root, +extern void build_base_rel(PlannerInfo *root, int relid); +extern RelOptInfo *build_other_rel(PlannerInfo *root, int relid); +extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid); +extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids); +extern RelOptInfo *build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 3b90cd7f7c..f0c2e64599 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -1,14 +1,13 @@ /*------------------------------------------------------------------------- * * paths.h - * prototypes for various files in optimizer/path (were separate - * header files) + * prototypes for various files in optimizer/path * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.83 2005/04/25 01:30:14 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.84 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,23 +23,23 @@ extern bool enable_geqo; extern int geqo_threshold; -extern RelOptInfo *make_one_rel(Query *root); -extern RelOptInfo *make_fromexpr_rel(Query *root, FromExpr *from); +extern RelOptInfo *make_one_rel(PlannerInfo *root); +extern RelOptInfo *make_fromexpr_rel(PlannerInfo *root, FromExpr *from); #ifdef OPTIMIZER_DEBUG -extern void debug_print_rel(Query *root, RelOptInfo *rel); +extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel); #endif /* * indxpath.c * routines to generate index paths */ -extern void create_index_paths(Query *root, RelOptInfo *rel); -extern List *generate_bitmap_or_paths(Query *root, RelOptInfo *rel, +extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel); +extern List *generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool isjoininner, Relids outer_relids); -extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel, +extern Path *best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, Relids outer_relids, JoinType jointype); extern List *group_clauses_by_indexkey(IndexOptInfo *index, List *clauses, List *outer_clauses, @@ -49,7 +48,7 @@ extern bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index); extern List *expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups); -extern void check_partial_indexes(Query *root, RelOptInfo *rel); +extern void check_partial_indexes(PlannerInfo *root, RelOptInfo *rel); extern bool pred_test(List *predicate_list, List *restrictinfo_list); extern List *flatten_clausegroups_list(List *clausegroups); @@ -57,19 +56,19 @@ extern List *flatten_clausegroups_list(List *clausegroups); * orindxpath.c * additional routines for indexable OR clauses */ -extern bool create_or_index_quals(Query *root, RelOptInfo *rel); +extern bool create_or_index_quals(PlannerInfo *root, RelOptInfo *rel); /* * tidpath.h * routines to generate tid paths */ -extern void create_tidscan_paths(Query *root, RelOptInfo *rel); +extern void create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel); /* * joinpath.c * routines to create join paths */ -extern void add_paths_to_joinrel(Query *root, RelOptInfo *joinrel, +extern void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, @@ -79,9 +78,9 @@ extern void add_paths_to_joinrel(Query *root, RelOptInfo *joinrel, * joinrels.c * routines to determine which relations to join */ -extern List *make_rels_by_joins(Query *root, int level, List **joinrels); -extern RelOptInfo *make_jointree_rel(Query *root, Node *jtnode); -extern RelOptInfo *make_join_rel(Query *root, +extern List *make_rels_by_joins(PlannerInfo *root, int level, List **joinrels); +extern RelOptInfo *make_jointree_rel(PlannerInfo *root, Node *jtnode); +extern RelOptInfo *make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype); @@ -97,10 +96,10 @@ typedef enum PATHKEYS_DIFFERENT /* neither pathkey includes the other */ } PathKeysComparison; -extern void add_equijoined_keys(Query *root, RestrictInfo *restrictinfo); -extern bool exprs_known_equal(Query *root, Node *item1, Node *item2); -extern void generate_implied_equalities(Query *root); -extern List *canonicalize_pathkeys(Query *root, List *pathkeys); +extern void add_equijoined_keys(PlannerInfo *root, RestrictInfo *restrictinfo); +extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2); +extern void generate_implied_equalities(PlannerInfo *root); +extern List *canonicalize_pathkeys(PlannerInfo *root, List *pathkeys); extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2); extern bool pathkeys_contained_in(List *keys1, List *keys2); extern PathKeysComparison compare_noncanonical_pathkeys(List *keys1, @@ -111,29 +110,29 @@ extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths, List *pathkeys, double fraction); -extern List *build_index_pathkeys(Query *root, IndexOptInfo *index, +extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir); -extern List *build_subquery_pathkeys(Query *root, RelOptInfo *rel, - Query *subquery); -extern List *build_join_pathkeys(Query *root, +extern List *convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, + List *subquery_pathkeys); +extern List *build_join_pathkeys(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys); extern List *make_pathkeys_for_sortclauses(List *sortclauses, List *tlist); -extern void cache_mergeclause_pathkeys(Query *root, +extern void cache_mergeclause_pathkeys(PlannerInfo *root, RestrictInfo *restrictinfo); -extern List *find_mergeclauses_for_pathkeys(Query *root, +extern List *find_mergeclauses_for_pathkeys(PlannerInfo *root, List *pathkeys, List *restrictinfos); -extern List *make_pathkeys_for_mergeclauses(Query *root, +extern List *make_pathkeys_for_mergeclauses(PlannerInfo *root, List *mergeclauses, RelOptInfo *rel); -extern int pathkeys_useful_for_merging(Query *root, +extern int pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys); -extern int pathkeys_useful_for_ordering(Query *root, List *pathkeys); -extern List *truncate_useless_pathkeys(Query *root, +extern int pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys); +extern List *truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys); diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h index 2f254016ef..f8ecd36110 100644 --- a/src/include/optimizer/plancat.h +++ b/src/include/optimizer/plancat.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.35 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.36 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ extern void get_relation_info(Oid relationObjectId, RelOptInfo *rel); -extern List *build_physical_tlist(Query *root, RelOptInfo *rel); +extern List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel); extern List *find_inheritance_children(Oid inhparent); @@ -27,12 +27,12 @@ extern bool has_subclass(Oid relationId); extern bool has_unique_index(RelOptInfo *rel, AttrNumber attno); -extern Selectivity restriction_selectivity(Query *root, +extern Selectivity restriction_selectivity(PlannerInfo *root, Oid operator, List *args, int varRelid); -extern Selectivity join_selectivity(Query *root, +extern Selectivity join_selectivity(PlannerInfo *root, Oid operator, List *args, JoinType jointype); diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index bb27bf01d5..4518635186 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.85 2005/05/22 22:30:20 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.86 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,33 +20,34 @@ /* * prototypes for plan/planmain.c */ -extern void query_planner(Query *root, List *tlist, double tuple_fraction, - Path **cheapest_path, Path **sorted_path); +extern void query_planner(PlannerInfo *root, List *tlist, + double tuple_fraction, + Path **cheapest_path, Path **sorted_path); /* * prototypes for plan/planagg.c */ -extern Plan *optimize_minmax_aggregates(Query *root, List *tlist, +extern Plan *optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path); /* * prototypes for plan/createplan.c */ -extern Plan *create_plan(Query *root, Path *best_path); +extern Plan *create_plan(PlannerInfo *root, Path *best_path); extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan); extern Append *make_append(List *appendplans, bool isTarget, List *tlist); -extern Sort *make_sort_from_sortclauses(Query *root, List *sortcls, +extern Sort *make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree); -extern Sort *make_sort_from_groupcols(Query *root, List *groupcls, +extern Sort *make_sort_from_groupcols(PlannerInfo *root, List *groupcls, AttrNumber *grpColIdx, Plan *lefttree); -extern List *order_qual_clauses(Query *root, List *clauses); -extern Agg *make_agg(Query *root, List *tlist, List *qual, +extern List *order_qual_clauses(PlannerInfo *root, List *clauses); +extern Agg *make_agg(PlannerInfo *root, List *tlist, List *qual, AggStrategy aggstrategy, int numGroupCols, AttrNumber *grpColIdx, long numGroups, int numAggs, Plan *lefttree); -extern Group *make_group(Query *root, List *tlist, List *qual, +extern Group *make_group(PlannerInfo *root, List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, double numGroups, Plan *lefttree); @@ -62,10 +63,10 @@ extern bool is_projection_capable_plan(Plan *plan); /* * prototypes for plan/initsplan.c */ -extern void add_base_rels_to_query(Query *root, Node *jtnode); -extern void build_base_rel_tlists(Query *root, List *final_tlist); -extern Relids distribute_quals_to_rels(Query *root, Node *jtnode); -extern void process_implied_equality(Query *root, +extern void add_base_rels_to_query(PlannerInfo *root, Node *jtnode); +extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist); +extern Relids distribute_quals_to_rels(PlannerInfo *root, Node *jtnode); +extern void process_implied_equality(PlannerInfo *root, Node *item1, Node *item2, Oid sortop1, Oid sortop2, Relids item1_relids, Relids item2_relids, diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index 1f1a6b91c2..37091c9f57 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.32 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.33 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,7 @@ extern ParamListInfo PlannerBoundParamList; /* current boundParams */ extern Plan *planner(Query *parse, bool isCursor, int cursorOptions, ParamListInfo boundParams); -extern Plan *subquery_planner(Query *parse, double tuple_fraction); +extern Plan *subquery_planner(Query *parse, double tuple_fraction, + List **subquery_pathkeys); #endif /* PLANNER_H */ diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h index 6a86b2e174..e4b9cb2f45 100644 --- a/src/include/optimizer/prep.h +++ b/src/include/optimizer/prep.h @@ -7,14 +7,13 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/prep.h,v 1.49 2005/03/28 00:58:26 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/prep.h,v 1.50 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef PREP_H #define PREP_H -#include "nodes/parsenodes.h" #include "nodes/plannodes.h" #include "nodes/relation.h" @@ -25,13 +24,13 @@ extern int from_collapse_limit; extern int join_collapse_limit; -extern Node *pull_up_IN_clauses(Query *parse, Node *node); -extern Node *pull_up_subqueries(Query *parse, Node *jtnode, +extern Node *pull_up_IN_clauses(PlannerInfo *root, Node *node); +extern Node *pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join); -extern void reduce_outer_joins(Query *parse); -extern Node *simplify_jointree(Query *parse, Node *jtnode); +extern void reduce_outer_joins(PlannerInfo *root); +extern Node *simplify_jointree(PlannerInfo *root, Node *jtnode); extern Relids get_relids_in_jointree(Node *jtnode); -extern Relids get_relids_for_join(Query *parse, int joinrelid); +extern Relids get_relids_for_join(PlannerInfo *root, int joinrelid); /* * prototypes for prepqual.c @@ -41,16 +40,16 @@ extern Expr *canonicalize_qual(Expr *qual); /* * prototypes for preptlist.c */ -extern List *preprocess_targetlist(Query *parse, List *tlist); +extern List *preprocess_targetlist(PlannerInfo *root, List *tlist); /* * prototypes for prepunion.c */ -extern Plan *plan_set_operations(Query *parse, List **sortClauses); +extern Plan *plan_set_operations(PlannerInfo *root, List **sortClauses); extern List *find_all_inheritors(Oid parentrel); -extern List *expand_inherited_rtentry(Query *parse, Index rti); +extern List *expand_inherited_rtentry(PlannerInfo *root, Index rti); extern Node *adjust_inherited_attrs(Node *node, Index old_rt_index, Oid old_relid, diff --git a/src/include/optimizer/restrictinfo.h b/src/include/optimizer/restrictinfo.h index 3760a65669..4fa6ace6ae 100644 --- a/src/include/optimizer/restrictinfo.h +++ b/src/include/optimizer/restrictinfo.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.29 2005/04/25 02:14:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.30 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "nodes/relation.h" + extern RestrictInfo *make_restrictinfo(Expr *clause, bool is_pushed_down, bool valid_everywhere); extern List *make_restrictinfo_from_bitmapqual(Path *bitmapqual, @@ -25,10 +26,10 @@ extern bool restriction_is_or_clause(RestrictInfo *restrictinfo); extern List *get_actual_clauses(List *restrictinfo_list); extern void get_actual_join_clauses(List *restrictinfo_list, List **joinquals, List **otherquals); -extern List *remove_redundant_join_clauses(Query *root, +extern List *remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list, bool isouterjoin); -extern List *select_nonredundant_join_clauses(Query *root, +extern List *select_nonredundant_join_clauses(PlannerInfo *root, List *restrictinfo_list, List *reference_list, bool isouterjoin); diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index 9381321a46..ccad3cd91b 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -5,26 +5,27 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.24 2005/04/11 23:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.25 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef SUBSELECT_H #define SUBSELECT_H -#include "nodes/parsenodes.h" #include "nodes/plannodes.h" +#include "nodes/relation.h" + extern Index PlannerQueryLevel; /* level of current query */ extern List *PlannerInitPlan; /* init subplans for current query */ extern List *PlannerParamList; /* to keep track of cross-level Params */ extern int PlannerPlanId; /* to assign unique ID to subquery plans */ -extern Node *convert_IN_to_join(Query *parse, SubLink *sublink); +extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink); extern Node *SS_replace_correlation_vars(Node *expr); extern Node *SS_process_sublinks(Node *expr, bool isQual); extern void SS_finalize_plan(Plan *plan, List *rtable); -extern Param *SS_make_initplan_from_plan(Query *root, Plan *plan, +extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan, Oid resulttype, int32 resulttypmod); #endif /* SUBSELECT_H */ diff --git a/src/include/optimizer/var.h b/src/include/optimizer/var.h index 4c21c12745..5ba6406ab0 100644 --- a/src/include/optimizer/var.h +++ b/src/include/optimizer/var.h @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * var.h - * prototypes for var.c. + * prototypes for optimizer/util/var.c. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.32 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.33 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,6 +25,6 @@ extern bool contain_vars_of_level(Node *node, int levelsup); extern bool contain_vars_above_level(Node *node, int levelsup); extern int find_minimum_var_level(Node *node); extern List *pull_var_clause(Node *node, bool includeUpperVars); -extern Node *flatten_join_alias_vars(Query *root, Node *node); +extern Node *flatten_join_alias_vars(PlannerInfo *root, Node *node); #endif /* VAR_H */ diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h index 5fbc9d3ae6..e54c11df36 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.22 2005/03/06 22:15:05 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.23 2005/06/05 22:32:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,7 @@ #define SELFUNCS_H #include "fmgr.h" -#include "nodes/parsenodes.h" +#include "nodes/relation.h" /* @@ -108,19 +108,19 @@ extern Datum icregexnejoinsel(PG_FUNCTION_ARGS); extern Datum nlikejoinsel(PG_FUNCTION_ARGS); extern Datum icnlikejoinsel(PG_FUNCTION_ARGS); -extern Selectivity booltestsel(Query *root, BoolTestType booltesttype, +extern Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype); -extern Selectivity nulltestsel(Query *root, NullTestType nulltesttype, +extern Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid); -extern void mergejoinscansel(Query *root, Node *clause, +extern void mergejoinscansel(PlannerInfo *root, Node *clause, Selectivity *leftscan, Selectivity *rightscan); -extern double estimate_num_groups(Query *root, List *groupExprs, +extern double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows); -extern Selectivity estimate_hash_bucketsize(Query *root, Node *hashkey, +extern Selectivity estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey, double nbuckets); extern Datum btcostestimate(PG_FUNCTION_ARGS);