1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-29 23:43:17 +03:00

Major planner/optimizer revision: get rid of PathOrder node type,

store all ordering information in pathkeys lists (which are now lists of
lists of PathKeyItem nodes, not just lists of lists of vars).  This was
a big win --- the code is smaller and IMHO more understandable than it
was, even though it handles more cases.  I believe the node changes will
not force an initdb for anyone; planner nodes don't show up in stored
rules.
This commit is contained in:
Tom Lane
1999-08-16 02:17:58 +00:00
parent 08320bfb22
commit e6381966c1
43 changed files with 1937 additions and 3270 deletions

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.36 1999/08/10 03:00:14 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.37 1999/08/16 02:17:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,11 +28,10 @@
static void add_restrict_and_join_to_rel(Query *root, Node *clause);
static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
Relids join_relids);
Relids join_relids);
static void add_vars_to_targetlist(Query *root, List *vars);
static MergeOrder *mergejoinop(Expr *clause);
static Oid hashjoinop(Expr *clause);
static void check_mergejoinable(RestrictInfo *restrictinfo);
static void check_hashjoinable(RestrictInfo *restrictinfo);
/*****************************************************************************
@@ -123,8 +122,8 @@ add_missing_vars_to_tlist(Query *root, List *tlist)
/*
* add_restrict_and_join_to_rels-
* Initializes RestrictInfo and JoinInfo fields of relation entries for all
* add_restrict_and_join_to_rels
* Fill RestrictInfo and JoinInfo lists of relation entries for all
* relations appearing within clauses. Creates new relation entries if
* necessary, adding them to *query_relation_list*.
*
@@ -140,11 +139,11 @@ add_restrict_and_join_to_rels(Query *root, List *clauses)
}
/*
* add_restrict_and_join_to_rel-
* add_restrict_and_join_to_rel
* Add clause information to either the 'RestrictInfo' or 'JoinInfo' field
* of a relation entry (depending on whether or not the clause is a join)
* by creating a new RestrictInfo node and setting appropriate fields
* within the nodes.
* (depending on whether the clause is a join) of each base relation
* mentioned in the clause. A RestrictInfo node is created and added to
* the appropriate list for each rel.
*/
static void
add_restrict_and_join_to_rel(Query *root, Node *clause)
@@ -154,9 +153,11 @@ add_restrict_and_join_to_rel(Query *root, Node *clause)
List *vars;
restrictinfo->clause = (Expr *) clause;
restrictinfo->indexids = NIL;
restrictinfo->mergejoinorder = (MergeOrder *) NULL;
restrictinfo->hashjoinoperator = (Oid) 0;
restrictinfo->subclauseindices = NIL;
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
restrictinfo->hashjoinoperator = InvalidOid;
/*
* The selectivity of the clause must be computed regardless of
@@ -196,7 +197,7 @@ add_restrict_and_join_to_rel(Query *root, Node *clause)
/*
* add_join_info_to_rels
* For every relation participating in a join clause, add 'restrictinfo' to
* the appropriate joininfo node (creating a new one and adding it to the
* the appropriate joininfo list (creating a new one and adding it to the
* appropriate rel node if necessary).
*
* 'restrictinfo' describes the join clause
@@ -211,21 +212,22 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
/* For every relid, find the joininfo, and add the proper join entries */
foreach(join_relid, join_relids)
{
int cur_relid = lfirsti(join_relid);
JoinInfo *joininfo;
Relids unjoined_relids = NIL;
List *rel;
List *otherrel;
/* Get the relids not equal to the current relid */
foreach(rel, join_relids)
foreach(otherrel, join_relids)
{
if (lfirsti(rel) != lfirsti(join_relid))
unjoined_relids = lappendi(unjoined_relids, lfirsti(rel));
if (lfirsti(otherrel) != cur_relid)
unjoined_relids = lappendi(unjoined_relids, lfirsti(otherrel));
}
/*
* Find or make the joininfo node for this combination of rels
*/
joininfo = find_joininfo_node(get_base_rel(root, lfirsti(join_relid)),
joininfo = find_joininfo_node(get_base_rel(root, cur_relid),
unjoined_relids);
/*
@@ -247,12 +249,8 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
/*
* set_joininfo_mergeable_hashable
* Set the MergeJoinable or HashJoinable field for every joininfo node
* (within a rel node) and the mergejoinorder or hashjoinop field for
* each restrictinfo node (within a joininfo node) for all relations in a
* query.
*
* Returns nothing.
* Examine each join clause used in a query and set the merge and hash
* info fields in those that are mergejoinable or hashjoinable.
*/
void
set_joininfo_mergeable_hashable(List *rel_list)
@@ -272,111 +270,102 @@ set_joininfo_mergeable_hashable(List *rel_list)
foreach(z, joininfo->jinfo_restrictinfo)
{
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(z);
Expr *clause = restrictinfo->clause;
if (is_joinable((Node *) clause))
{
if (_enable_mergejoin_)
{
MergeOrder *sortop = mergejoinop(clause);
if (sortop)
{
restrictinfo->mergejoinorder = sortop;
joininfo->mergejoinable = true;
}
}
if (_enable_hashjoin_)
{
Oid hashop = hashjoinop(clause);
if (hashop)
{
restrictinfo->hashjoinoperator = hashop;
joininfo->hashjoinable = true;
}
}
}
if (_enable_mergejoin_)
check_mergejoinable(restrictinfo);
if (_enable_hashjoin_)
check_hashjoinable(restrictinfo);
}
}
}
}
/*
* mergejoinop
* Returns a MergeOrder node for 'clause' iff 'clause' is mergejoinable,
* i.e., both operands are single vars and the operator is
* a mergejoinable operator.
* check_mergejoinable
* If the restrictinfo's clause is mergejoinable, set the mergejoin
* info fields in the restrictinfo.
*
* Currently, we support mergejoin for binary opclauses where
* both operands are simple Vars and the operator is a mergejoinable
* operator. (Note: since we are only examining clauses that were
* classified as joins, it is certain that the two Vars belong to
* different relations... if we accepted more general clause structures
* we might need to check that the two sides refer to different rels...)
*/
static MergeOrder *
mergejoinop(Expr *clause)
static void
check_mergejoinable(RestrictInfo *restrictinfo)
{
Expr *clause = restrictinfo->clause;
Var *left,
*right;
Oid opno,
leftOp,
rightOp;
bool sortable;
if (!is_opclause((Node *) clause))
return NULL;
if (! is_opclause((Node *) clause))
return;
left = get_leftop(clause);
right = get_rightop(clause);
/* caution: is_opclause accepts more than I do, so check it */
if (!right)
return NULL; /* unary opclauses need not apply */
if (! right)
return; /* unary opclauses need not apply */
if (!IsA(left, Var) || !IsA(right, Var))
return NULL;
return;
opno = ((Oper *) clause->oper)->opno;
sortable = op_mergejoinable(opno,
left->vartype,
right->vartype,
&leftOp,
&rightOp);
if (sortable)
if (op_mergejoinable(opno,
left->vartype,
right->vartype,
&leftOp,
&rightOp))
{
MergeOrder *morder = makeNode(MergeOrder);
morder->join_operator = opno;
morder->left_operator = leftOp;
morder->right_operator = rightOp;
morder->left_type = left->vartype;
morder->right_type = right->vartype;
return morder;
restrictinfo->mergejoinoperator = opno;
restrictinfo->left_sortop = leftOp;
restrictinfo->right_sortop = rightOp;
}
else
return NULL;
}
/*
* hashjoinop
* Returns the hashjoin operator iff 'clause' is hashjoinable,
* i.e., both operands are single vars and the operator is
* a hashjoinable operator.
* check_hashjoinable
* If the restrictinfo's clause is hashjoinable, set the hashjoin
* info fields in the restrictinfo.
*
* Currently, we support hashjoin for binary opclauses where
* both operands are simple Vars and the operator is a hashjoinable
* operator. (Note: since we are only examining clauses that were
* classified as joins, it is certain that the two Vars belong to
* different relations... if we accepted more general clause structures
* we might need to check that the two sides refer to different rels...)
*/
static Oid
hashjoinop(Expr *clause)
static void
check_hashjoinable(RestrictInfo *restrictinfo)
{
Expr *clause = restrictinfo->clause;
Var *left,
*right;
Oid opno;
if (!is_opclause((Node *) clause))
return InvalidOid;
if (! is_opclause((Node *) clause))
return;
left = get_leftop(clause);
right = get_rightop(clause);
/* caution: is_opclause accepts more than I do, so check it */
if (!right)
return InvalidOid; /* unary opclauses need not apply */
if (! right)
return; /* unary opclauses need not apply */
if (!IsA(left, Var) || !IsA(right, Var))
return InvalidOid;
return;
return op_hashjoinable(((Oper *) clause->oper)->opno,
left->vartype,
right->vartype);
opno = ((Oper *) clause->oper)->opno;
if (op_hashjoinable(opno,
left->vartype,
right->vartype))
{
restrictinfo->hashjoinoperator = opno;
}
}