Remove planner's private fields from Query struct, and put them into
a new PlannerInfo struct, which is passed around instead of the bare Query in all the planning code. This commit is essentially just a code-beautification exercise, but it does open the door to making larger changes to the planner data structures without having to muck with the widely-known Query struct.
This commit is contained in:
parent
22dbd54047
commit
9ab4d98168
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.4 2005/04/20 22:19:58 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.5 2005/06/05 22:32:53 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="indexam">
|
||||
|
@ -319,7 +319,7 @@ amrestrpos (IndexScanDesc scan);
|
|||
<para>
|
||||
<programlisting>
|
||||
void
|
||||
amcostestimate (Query *root,
|
||||
amcostestimate (PlannerInfo *root,
|
||||
IndexOptInfo *index,
|
||||
List *indexQuals,
|
||||
Cost *indexStartupCost,
|
||||
|
@ -656,7 +656,7 @@ amcostestimate (Query *root,
|
|||
|
||||
<programlisting>
|
||||
void
|
||||
amcostestimate (Query *root,
|
||||
amcostestimate (PlannerInfo *root,
|
||||
IndexOptInfo *index,
|
||||
List *indexQuals,
|
||||
Cost *indexStartupCost,
|
||||
|
@ -672,7 +672,7 @@ amcostestimate (Query *root,
|
|||
<term>root</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The query being processed.
|
||||
The planner's information about the query being processed.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,15 +201,19 @@ 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 = pull_up_IN_clauses(root,
|
||||
parse->jointree->quals);
|
||||
|
||||
/*
|
||||
|
@ -211,7 +221,7 @@ subquery_planner(Query *parse, double tuple_fraction)
|
|||
* 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,
|
||||
/*
|
||||
* 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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue