Commit 78114cd4 authored by Tom Lane's avatar Tom Lane

Further planner/optimizer cleanups. Move all set_tlist_references

and fix_opids processing to a single recursive pass over the plan tree
executed at the very tail end of planning, rather than haphazardly here
and there at different places.  Now that tlist Vars do not get modified
until the very end, it's possible to get rid of the klugy var_equal and
match_varid partial-matching routines, and just use plain equal()
throughout the optimizer.  This is a step towards allowing merge and
hash joins to be done on expressions instead of only Vars ...
parent db436adf
...@@ -2475,7 +2475,7 @@ having clause} is found. ...@@ -2475,7 +2475,7 @@ having clause} is found.
+ if(node->plan.qual != NULL) + if(node->plan.qual != NULL)
+ { + {
+ qual_result = + qual_result =
+ ExecQual(fix_opids(node->plan.qual), + ExecQual(node->plan.qual,
+ econtext); + econtext);
+ } + }
+ if (oneTuple) pfree(oneTuple); + if (oneTuple) pfree(oneTuple);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.9 1999/07/17 20:16:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.10 1999/08/22 20:14:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h" #include "optimizer/prep.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -142,7 +143,7 @@ DefineIndex(char *heapRelationName, ...@@ -142,7 +143,7 @@ DefineIndex(char *heapRelationName,
if (predicate != NULL && rangetable != NIL) if (predicate != NULL && rangetable != NIL)
{ {
cnfPred = cnfify((Expr *) copyObject(predicate), true); cnfPred = cnfify((Expr *) copyObject(predicate), true);
fix_opids(cnfPred); fix_opids((Node *) cnfPred);
CheckPredicate(cnfPred, rangetable, relationId); CheckPredicate(cnfPred, rangetable, relationId);
} }
...@@ -285,7 +286,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -285,7 +286,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
if (rangetable != NIL) if (rangetable != NIL)
{ {
cnfPred = cnfify((Expr *) copyObject(predicate), true); cnfPred = cnfify((Expr *) copyObject(predicate), true);
fix_opids(cnfPred); fix_opids((Node *) cnfPred);
CheckPredicate(cnfPred, rangetable, relationId); CheckPredicate(cnfPred, rangetable, relationId);
} }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "executor/executor.h" #include "executor/executor.h"
#include "executor/nodeAgg.h" #include "executor/nodeAgg.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/syscache.h" #include "utils/syscache.h"
...@@ -443,7 +442,7 @@ ExecAgg(Agg *node) ...@@ -443,7 +442,7 @@ ExecAgg(Agg *node)
* qualifications it is ignored and the next group is fetched * qualifications it is ignored and the next group is fetched
*/ */
if (node->plan.qual != NULL) if (node->plan.qual != NULL)
qual_result = ExecQual(fix_opids(node->plan.qual), econtext); qual_result = ExecQual(node->plan.qual, econtext);
else else
qual_result = false; qual_result = false;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.17 1999/08/21 03:48:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.18 1999/08/22 20:14:59 tgl Exp $
* *
* NOTES * NOTES
* Creator functions in POSTGRES 4.2 are generated automatically. Most of * Creator functions in POSTGRES 4.2 are generated automatically. Most of
...@@ -52,9 +52,7 @@ makeVar(Index varno, ...@@ -52,9 +52,7 @@ makeVar(Index varno,
AttrNumber varattno, AttrNumber varattno,
Oid vartype, Oid vartype,
int32 vartypmod, int32 vartypmod,
Index varlevelsup, Index varlevelsup)
Index varnoold,
AttrNumber varoattno)
{ {
Var *var = makeNode(Var); Var *var = makeNode(Var);
...@@ -63,8 +61,14 @@ makeVar(Index varno, ...@@ -63,8 +61,14 @@ makeVar(Index varno,
var->vartype = vartype; var->vartype = vartype;
var->vartypmod = vartypmod; var->vartypmod = vartypmod;
var->varlevelsup = varlevelsup; var->varlevelsup = varlevelsup;
var->varnoold = varnoold; /*
var->varoattno = varoattno; * Since few if any routines ever create Var nodes with varnoold/varoattno
* different from varno/varattno, we don't provide separate arguments
* for them, but just initialize them to the given varno/varattno.
* This reduces code clutter and chance of error for most callers.
*/
var->varnoold = varno;
var->varoattno = varattno;
return var; return var;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.44 1999/08/06 04:00:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.45 1999/08/22 20:14:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -431,7 +431,7 @@ compute_rel_size(RelOptInfo *rel) ...@@ -431,7 +431,7 @@ compute_rel_size(RelOptInfo *rel)
int int
compute_rel_width(RelOptInfo *rel) compute_rel_width(RelOptInfo *rel)
{ {
return compute_targetlist_width(get_actual_tlist(rel->targetlist)); return compute_targetlist_width(rel->targetlist);
} }
/* /*
...@@ -448,8 +448,7 @@ compute_targetlist_width(List *targetlist) ...@@ -448,8 +448,7 @@ compute_targetlist_width(List *targetlist)
foreach(temp_tl, targetlist) foreach(temp_tl, targetlist)
{ {
tuple_width = tuple_width + tuple_width += compute_attribute_width(lfirst(temp_tl));
compute_attribute_width(lfirst(temp_tl));
} }
return tuple_width; return tuple_width;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.15 1999/08/21 03:49:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.16 1999/08/22 20:14:42 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
static PathKeyItem *makePathKeyItem(Node *key, Oid sortop); static PathKeyItem *makePathKeyItem(Node *key, Oid sortop);
static bool pathkeyitem_equal(PathKeyItem *a, PathKeyItem *b);
static bool pathkeyitem_member(PathKeyItem *a, List *l);
static Var *find_indexkey_var(int indexkey, List *tlist); static Var *find_indexkey_var(int indexkey, List *tlist);
static List *build_join_pathkey(List *pathkeys, List *join_rel_tlist, static List *build_join_pathkey(List *pathkeys, List *join_rel_tlist,
List *joinclauses); List *joinclauses);
...@@ -118,45 +116,6 @@ makePathKeyItem(Node *key, Oid sortop) ...@@ -118,45 +116,6 @@ makePathKeyItem(Node *key, Oid sortop)
* PATHKEY COMPARISONS * PATHKEY COMPARISONS
****************************************************************************/ ****************************************************************************/
/*
* Compare two pathkey items for equality.
*
* This is unlike straight equal() because when the two keys are both Vars,
* we want to apply the weaker var_equal() condition (doesn't check varnoold
* or varoattno). But if that fails, try equal() so that we recognize
* functional-index keys.
*/
static bool
pathkeyitem_equal (PathKeyItem *a, PathKeyItem *b)
{
Assert(a && IsA(a, PathKeyItem));
Assert(b && IsA(b, PathKeyItem));
if (a->sortop != b->sortop)
return false;
if (var_equal((Var *) a->key, (Var *) b->key))
return true;
return equal(a->key, b->key);
}
/*
* member() test using pathkeyitem_equal
*/
static bool
pathkeyitem_member (PathKeyItem *a, List *l)
{
List *i;
Assert(a && IsA(a, PathKeyItem));
foreach(i, l)
{
if (pathkeyitem_equal(a, (PathKeyItem *) lfirst(i)))
return true;
}
return false;
}
/* /*
* compare_pathkeys * compare_pathkeys
* Compare two pathkeys to see if they are equivalent, and if not whether * Compare two pathkeys to see if they are equivalent, and if not whether
...@@ -191,7 +150,7 @@ compare_pathkeys(List *keys1, List *keys2) ...@@ -191,7 +150,7 @@ compare_pathkeys(List *keys1, List *keys2)
{ {
foreach(i, subkey1) foreach(i, subkey1)
{ {
if (! pathkeyitem_member((PathKeyItem *) lfirst(i), subkey2)) if (! member(lfirst(i), subkey2))
{ {
key1_subsetof_key2 = false; key1_subsetof_key2 = false;
break; break;
...@@ -203,7 +162,7 @@ compare_pathkeys(List *keys1, List *keys2) ...@@ -203,7 +162,7 @@ compare_pathkeys(List *keys1, List *keys2)
{ {
foreach(i, subkey2) foreach(i, subkey2)
{ {
if (! pathkeyitem_member((PathKeyItem *) lfirst(i), subkey1)) if (! member(lfirst(i), subkey1))
{ {
key2_subsetof_key1 = false; key2_subsetof_key1 = false;
break; break;
...@@ -336,8 +295,8 @@ build_index_pathkeys(Query *root, RelOptInfo *rel, RelOptInfo *index) ...@@ -336,8 +295,8 @@ build_index_pathkeys(Query *root, RelOptInfo *rel, RelOptInfo *index)
int32 type_mod = get_atttypmod(reloid, varattno); int32 type_mod = get_atttypmod(reloid, varattno);
funcargs = lappend(funcargs, funcargs = lappend(funcargs,
makeVar(relid, varattno, vartypeid, type_mod, makeVar(relid, varattno, vartypeid,
0, relid, varattno)); type_mod, 0));
indexkeys++; indexkeys++;
} }
...@@ -483,13 +442,13 @@ build_join_pathkey(List *pathkey, ...@@ -483,13 +442,13 @@ build_join_pathkey(List *pathkey,
foreach(i, pathkey) foreach(i, pathkey)
{ {
PathKeyItem *key = (PathKeyItem *) lfirst(i); PathKeyItem *key = (PathKeyItem *) lfirst(i);
Expr *tlist_key; Node *tlist_key;
Assert(key && IsA(key, PathKeyItem)); Assert(key && IsA(key, PathKeyItem));
tlist_key = matching_tlist_var((Var *) key->key, join_rel_tlist); tlist_key = matching_tlist_expr(key->key, join_rel_tlist);
if (tlist_key) if (tlist_key)
new_pathkey = lcons(makePathKeyItem((Node *) tlist_key, new_pathkey = lcons(makePathKeyItem(tlist_key,
key->sortop), key->sortop),
new_pathkey); new_pathkey);
...@@ -498,17 +457,17 @@ build_join_pathkey(List *pathkey, ...@@ -498,17 +457,17 @@ build_join_pathkey(List *pathkey,
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(j); RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(j);
Expr *joinclause = restrictinfo->clause; Expr *joinclause = restrictinfo->clause;
/* We assume the clause is a binary opclause... */ /* We assume the clause is a binary opclause... */
Var *l = get_leftop(joinclause); Node *l = (Node *) get_leftop(joinclause);
Var *r = get_rightop(joinclause); Node *r = (Node *) get_rightop(joinclause);
Var *other_var = NULL; Node *other_var = NULL;
Oid other_sortop = InvalidOid; Oid other_sortop = InvalidOid;
if (var_equal((Var *) key->key, l)) if (equal(key->key, l))
{ {
other_var = r; other_var = r;
other_sortop = restrictinfo->right_sortop; other_sortop = restrictinfo->right_sortop;
} }
else if (var_equal((Var *) key->key, r)) else if (equal(key->key, r))
{ {
other_var = l; other_var = l;
other_sortop = restrictinfo->left_sortop; other_sortop = restrictinfo->left_sortop;
...@@ -516,9 +475,9 @@ build_join_pathkey(List *pathkey, ...@@ -516,9 +475,9 @@ build_join_pathkey(List *pathkey,
if (other_var && other_sortop) if (other_var && other_sortop)
{ {
tlist_key = matching_tlist_var(other_var, join_rel_tlist); tlist_key = matching_tlist_expr(other_var, join_rel_tlist);
if (tlist_key) if (tlist_key)
new_pathkey = lcons(makePathKeyItem((Node *) tlist_key, new_pathkey = lcons(makePathKeyItem(tlist_key,
other_sortop), other_sortop),
new_pathkey); new_pathkey);
} }
...@@ -638,20 +597,17 @@ find_mergeclauses_for_pathkeys(List *pathkeys, List *restrictinfos) ...@@ -638,20 +597,17 @@ find_mergeclauses_for_pathkeys(List *pathkeys, List *restrictinfos)
foreach(j, pathkey) foreach(j, pathkey)
{ {
PathKeyItem *keyitem = lfirst(j); PathKeyItem *keyitem = lfirst(j);
Var *keyvar = (Var *) keyitem->key; Node *key = keyitem->key;
List *k; List *k;
if (! IsA(keyvar, Var))
continue; /* for now, only Vars can be mergejoined */
foreach(k, restrictinfos) foreach(k, restrictinfos)
{ {
RestrictInfo *restrictinfo = lfirst(k); RestrictInfo *restrictinfo = lfirst(k);
Assert(restrictinfo->mergejoinoperator != InvalidOid); Assert(restrictinfo->mergejoinoperator != InvalidOid);
if ((var_equal(keyvar, get_leftop(restrictinfo->clause)) || if ((equal(key, get_leftop(restrictinfo->clause)) ||
var_equal(keyvar, get_rightop(restrictinfo->clause))) && equal(key, get_rightop(restrictinfo->clause))) &&
! member(restrictinfo, mergeclauses)) ! member(restrictinfo, mergeclauses))
{ {
matched_restrictinfo = restrictinfo; matched_restrictinfo = restrictinfo;
...@@ -705,23 +661,24 @@ make_pathkeys_for_mergeclauses(List *mergeclauses, List *tlist) ...@@ -705,23 +661,24 @@ make_pathkeys_for_mergeclauses(List *mergeclauses, List *tlist)
foreach(i, mergeclauses) foreach(i, mergeclauses)
{ {
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i); RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
Var *key; Node *key;
Oid sortop; Oid sortop;
Assert(restrictinfo->mergejoinoperator != InvalidOid);
/* /*
* Find the key and sortop needed for this mergeclause. * Find the key and sortop needed for this mergeclause.
* *
* We can use either side of the mergeclause, since we haven't yet * We can use either side of the mergeclause, since we haven't yet
* committed to which side will be inner. * committed to which side will be inner.
*/ */
Assert(restrictinfo->mergejoinoperator != InvalidOid); key = matching_tlist_expr((Node *) get_leftop(restrictinfo->clause),
key = (Var *) matching_tlist_var(get_leftop(restrictinfo->clause), tlist);
tlist);
sortop = restrictinfo->left_sortop; sortop = restrictinfo->left_sortop;
if (! key) if (! key)
{ {
key = (Var *) matching_tlist_var(get_rightop(restrictinfo->clause), key = matching_tlist_expr((Node *) get_rightop(restrictinfo->clause),
tlist); tlist);
sortop = restrictinfo->right_sortop; sortop = restrictinfo->right_sortop;
} }
if (! key) if (! key)
...@@ -730,7 +687,7 @@ make_pathkeys_for_mergeclauses(List *mergeclauses, List *tlist) ...@@ -730,7 +687,7 @@ make_pathkeys_for_mergeclauses(List *mergeclauses, List *tlist)
* Add a pathkey sublist for this sort item * Add a pathkey sublist for this sort item
*/ */
pathkeys = lappend(pathkeys, pathkeys = lappend(pathkeys,
lcons(makePathKeyItem((Node *) key, sortop), lcons(makePathKeyItem(key, sortop),
NIL)); NIL));
} }
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.37 1999/08/16 02:17:54 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.38 1999/08/22 20:14:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -104,8 +104,7 @@ add_missing_vars_to_tlist(Query *root, List *tlist) ...@@ -104,8 +104,7 @@ add_missing_vars_to_tlist(Query *root, List *tlist)
/* add it to base_rel_list */ /* add it to base_rel_list */
rel = get_base_rel(root, varno); rel = get_base_rel(root, varno);
/* give it a dummy tlist entry for its OID */ /* give it a dummy tlist entry for its OID */
var = makeVar(varno, ObjectIdAttributeNumber, var = makeVar(varno, ObjectIdAttributeNumber, OIDOID, -1, 0);
OIDOID, -1, 0, varno, ObjectIdAttributeNumber);
add_var_to_tlist(rel, var); add_var_to_tlist(rel, var);
} }
pfree(relids); pfree(relids);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.41 1999/08/21 03:49:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.42 1999/08/22 20:14:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
static Plan *subplanner(Query *root, List *flat_tlist, List *qual); static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
/* /*
* query_planner * query_planner
...@@ -84,11 +83,6 @@ query_planner(Query *root, ...@@ -84,11 +83,6 @@ query_planner(Query *root,
* topmost result node. * topmost result node.
*/ */
qual = pull_constant_clauses(qual, &constant_qual); qual = pull_constant_clauses(qual, &constant_qual);
/*
* The opids for the variable qualifications will be fixed later, but
* someone seems to think that the constant quals need to be fixed here.
*/
fix_opids(constant_qual);
/* /*
* Create a target list that consists solely of (resdom var) target * Create a target list that consists solely of (resdom var) target
...@@ -124,8 +118,7 @@ query_planner(Query *root, ...@@ -124,8 +118,7 @@ query_planner(Query *root,
{ {
SeqScan *scan = make_seqscan(tlist, SeqScan *scan = make_seqscan(tlist,
NIL, NIL,
root->resultRelation, root->resultRelation);
(Plan *) NULL);
if (constant_qual != NULL) if (constant_qual != NULL)
return ((Plan *) make_result(tlist, return ((Plan *) make_result(tlist,
...@@ -141,14 +134,10 @@ query_planner(Query *root, ...@@ -141,14 +134,10 @@ query_planner(Query *root,
} }
/* /*
* Find the subplan (access path) and destructively modify the target * Choose the best access path and build a plan for it.
* list of the newly created subplan to contain the appropriate join
* references.
*/ */
subplan = subplanner(root, level_tlist, qual); subplan = subplanner(root, level_tlist, qual);
set_tlist_references(subplan);
/* /*
* Build a result node linking the plan if we have constant quals * Build a result node linking the plan if we have constant quals
*/ */
...@@ -158,33 +147,24 @@ query_planner(Query *root, ...@@ -158,33 +147,24 @@ query_planner(Query *root,
(Node *) constant_qual, (Node *) constant_qual,
subplan); subplan);
/*
* Fix all varno's of the Result's node target list.
*/
set_tlist_references(subplan);
root->query_pathkeys = NIL; /* result is unordered, no? */ root->query_pathkeys = NIL; /* result is unordered, no? */
return subplan; return subplan;
} }
/* /*
* fix up the flattened target list of the plan root node so that * Replace the toplevel plan node's flattened target list with the
* expressions are evaluated. this forces expression evaluations that * targetlist given by my caller, so that expressions are evaluated.
* may involve expensive function calls to be delayed to the very last
* stage of query execution. this could be bad. but it is joey's
* responsibility to optimally push these expressions down the plan
* tree. -- Wei
* *
* Note: formerly there was a test here to skip the unflatten call if * This implies that all expression evaluations are done at the root
* we expected union_planner to insert a Group or Agg node above our * of the plan tree. Once upon a time there was code to try to push
* result. However, now union_planner tells us exactly what it wants * expensive function calls down to lower plan nodes, but that's dead
* returned, and we just do it. Much cleaner. * code and has been for a long time...
*/ */
else else
{ {
subplan->targetlist = unflatten_tlist(tlist, subplan->targetlist = tlist;
subplan->targetlist);
return subplan; return subplan;
} }
...@@ -330,36 +310,11 @@ subplanner(Query *root, ...@@ -330,36 +310,11 @@ subplanner(Query *root,
/* Nothing for it but to sort the cheapestpath... /* Nothing for it but to sort the cheapestpath...
* *
* we indicate we failed to sort the plan, and let the caller * We indicate we failed to sort the plan, and let the caller
* stick the appropriate sortplan on top. * stick the appropriate sort node on top. union_planner has to be
* able to add a sort node anyway, so no need for extra code here.
*/ */
root->query_pathkeys = NIL; /* sorry, it ain't sorted */ root->query_pathkeys = NIL; /* sorry, it ain't sorted */
return create_plan(final_rel->cheapestpath); return create_plan(final_rel->cheapestpath);
} }
/*****************************************************************************
*
*****************************************************************************/
static Result *
make_result(List *tlist,
Node *resconstantqual,
Plan *subplan)
{
Result *node = makeNode(Result);
Plan *plan = &node->plan;
#ifdef NOT_USED
tlist = generate_fjoin(tlist);
#endif
plan->cost = (subplan ? subplan->cost : 0);
plan->state = (EState *) NULL;
plan->targetlist = tlist;
plan->lefttree = subplan;
plan->righttree = NULL;
node->resconstantqual = resconstantqual;
node->resstate = NULL;
return node;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.63 1999/08/21 03:49:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.64 1999/08/22 20:14:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -70,6 +70,8 @@ planner(Query *parse) ...@@ -70,6 +70,8 @@ planner(Query *parse)
} }
result_plan->nParamExec = length(PlannerParamVar); result_plan->nParamExec = length(PlannerParamVar);
set_plan_references(result_plan);
return result_plan; return result_plan;
} }
...@@ -173,8 +175,7 @@ union_planner(Query *parse) ...@@ -173,8 +175,7 @@ union_planner(Query *parse)
0, 0,
true); true);
var = makeVar(rowmark->rti, -1, TIDOID, var = makeVar(rowmark->rti, -1, TIDOID, -1, 0);
-1, 0, rowmark->rti, -1);
ctid = makeTargetEntry(resdom, (Node *) var); ctid = makeTargetEntry(resdom, (Node *) var);
tlist = lappend(tlist, ctid); tlist = lappend(tlist, ctid);
...@@ -279,6 +280,8 @@ union_planner(Query *parse) ...@@ -279,6 +280,8 @@ union_planner(Query *parse)
*/ */
if (parse->havingQual) if (parse->havingQual)
{ {
List *ql;
/* convert the havingQual to conjunctive normal form (cnf) */ /* convert the havingQual to conjunctive normal form (cnf) */
parse->havingQual = (Node *) cnfify((Expr *) parse->havingQual, true); parse->havingQual = (Node *) cnfify((Expr *) parse->havingQual, true);
...@@ -295,13 +298,21 @@ union_planner(Query *parse) ...@@ -295,13 +298,21 @@ union_planner(Query *parse)
* Check for ungrouped variables passed to subplans. (Probably * Check for ungrouped variables passed to subplans. (Probably
* this should be done for the targetlist as well???) * this should be done for the targetlist as well???)
*/ */
check_having_for_ungrouped_vars(parse->havingQual, if (check_subplans_for_ungrouped_vars(parse->havingQual,
parse->groupClause, parse->groupClause,
parse->targetList); parse->targetList))
elog(ERROR, "Sub-SELECT in HAVING clause must use only GROUPed attributes from outer SELECT");
} }
/* Calculate the opfids from the opnos */ /*
parse->havingQual = (Node *) fix_opids((List *) parse->havingQual); * Require an aggregate function to appear in each clause of the
* havingQual (else it could have been done as a WHERE constraint).
*/
foreach(ql, (List *) parse->havingQual)
{
if (pull_agg_clause(lfirst(ql)) == NIL)
elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
}
} }
/* /*
...@@ -314,13 +325,6 @@ union_planner(Query *parse) ...@@ -314,13 +325,6 @@ union_planner(Query *parse)
/* HAVING clause, if any, becomes qual of the Agg node */ /* HAVING clause, if any, becomes qual of the Agg node */
result_plan->qual = (List *) parse->havingQual; result_plan->qual = (List *) parse->havingQual;
/*
* Update vars to refer to subplan result tuples, and
* make sure there is an Aggref in every HAVING clause.
*/
if (!set_agg_tlist_references((Agg *) result_plan))
elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
/* /*
* Assume result is not ordered suitably for ORDER BY. * Assume result is not ordered suitably for ORDER BY.
* XXX it might be; improve this! * XXX it might be; improve this!
...@@ -474,7 +478,6 @@ make_groupplan(List *group_tlist, ...@@ -474,7 +478,6 @@ make_groupplan(List *group_tlist,
Plan *subplan) Plan *subplan)
{ {
int numCols = length(groupClause); int numCols = length(groupClause);
Group *grpplan;
if (! is_sorted) if (! is_sorted)
{ {
...@@ -515,21 +518,8 @@ make_groupplan(List *group_tlist, ...@@ -515,21 +518,8 @@ make_groupplan(List *group_tlist,
keyno); keyno);
} }
/* return (Plan *) make_group(group_tlist, tuplePerGroup, numCols,
* Fix variables in tlist (should be done somewhere else?) grpColIdx, subplan);
*/
group_tlist = copyObject(group_tlist); /* necessary?? */
replace_tlist_with_subplan_refs(group_tlist,
(Index) 0,
subplan->targetlist);
/*
* Make the Group node
*/
grpplan = make_group(group_tlist, tuplePerGroup, numCols,
grpColIdx, subplan);
return (Plan *) grpplan;
} }
/* /*
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.22 1999/08/21 03:49:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.23 1999/08/22 20:14:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,29 +48,13 @@ int PlannerPlanId; /* to assign unique ID to subquery plans */ ...@@ -48,29 +48,13 @@ int PlannerPlanId; /* to assign unique ID to subquery plans */
static int static int
_new_param(Var *var, int varlevel) _new_param(Var *var, int varlevel)
{ {
List *last; Var *paramVar = (Var *) copyObject(var);
int i = 0;
if (PlannerParamVar == NULL) paramVar->varlevelsup = varlevel;
last = PlannerParamVar = makeNode(List);
else
{
for (last = PlannerParamVar;;)
{
i++;
if (lnext(last) == NULL)
break;
last = lnext(last);
}
lnext(last) = makeNode(List);
last = lnext(last);
}
lnext(last) = NULL; PlannerParamVar = lappend(PlannerParamVar, paramVar);
lfirst(last) = makeVar(var->varno, var->varattno, var->vartype,
var->vartypmod, varlevel, var->varnoold, var->varoattno);
return i; return length(PlannerParamVar) - 1;
} }
/* /*
...@@ -193,8 +177,7 @@ _make_subplan(SubLink *slink) ...@@ -193,8 +177,7 @@ _make_subplan(SubLink *slink)
List *rside = lnext(((Expr *) lfirst(lst))->args); List *rside = lnext(((Expr *) lfirst(lst))->args);
TargetEntry *te = nth(i, plan->targetlist); TargetEntry *te = nth(i, plan->targetlist);
Var *var = makeVar(0, 0, te->resdom->restype, Var *var = makeVar(0, 0, te->resdom->restype,
te->resdom->restypmod, te->resdom->restypmod, 0);
0, 0, 0);
Param *prm = makeNode(Param); Param *prm = makeNode(Param);
prm->paramkind = PARAM_EXEC; prm->paramkind = PARAM_EXEC;
...@@ -214,7 +197,7 @@ _make_subplan(SubLink *slink) ...@@ -214,7 +197,7 @@ _make_subplan(SubLink *slink)
} }
else if (node->parParam == NULL && slink->subLinkType == EXISTS_SUBLINK) else if (node->parParam == NULL && slink->subLinkType == EXISTS_SUBLINK)
{ {
Var *var = makeVar(0, 0, BOOLOID, -1, 0, 0, 0); Var *var = makeVar(0, 0, BOOLOID, -1, 0);
Param *prm = makeNode(Param); Param *prm = makeNode(Param);
prm->paramkind = PARAM_EXEC; prm->paramkind = PARAM_EXEC;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.30 1999/08/21 03:49:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.31 1999/08/22 20:14:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -59,8 +59,6 @@ preprocess_targetlist(List *tlist, ...@@ -59,8 +59,6 @@ preprocess_targetlist(List *tlist,
*/ */
expanded_tlist = expand_targetlist(tlist, relid, command_type, result_relation); expanded_tlist = expand_targetlist(tlist, relid, command_type, result_relation);
/* XXX should the fix-opids be this early?? */
fix_opids(expanded_tlist);
t_list = copyObject(expanded_tlist); t_list = copyObject(expanded_tlist);
/* ------------------ /* ------------------
...@@ -87,7 +85,7 @@ preprocess_targetlist(List *tlist, ...@@ -87,7 +85,7 @@ preprocess_targetlist(List *tlist,
0, 0,
true); true);
var = makeVar(result_relation, -1, TIDOID, -1, 0, result_relation, -1); var = makeVar(result_relation, -1, TIDOID, -1, 0);
ctid = makeTargetEntry(resdom, (Node *) var); ctid = makeTargetEntry(resdom, (Node *) var);
t_list = lappend(t_list, ctid); t_list = lappend(t_list, ctid);
...@@ -340,8 +338,8 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type) ...@@ -340,8 +338,8 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
Var *temp_var; Var *temp_var;
TargetEntry *temp_tle; TargetEntry *temp_tle;
temp_var = makeVar(rt_index, attno, atttype, atttypmod, temp_var = makeVar(rt_index, attno, atttype,
0, rt_index, attno); atttypmod, 0);
temp_tle = makeTargetEntry(makeResdom(attno, temp_tle = makeTargetEntry(makeResdom(attno,
atttype, atttype,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.47 1999/08/16 02:17:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.48 1999/08/22 20:14:53 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -24,11 +24,19 @@ ...@@ -24,11 +24,19 @@
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/internal.h" #include "optimizer/internal.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h" #include "optimizer/var.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
static bool fix_opids_walker(Node *node, void *context); typedef struct {
List *groupClause;
List *targetList;
} check_subplans_for_ungrouped_vars_context;
static bool pull_agg_clause_walker(Node *node, List **listptr);
static bool check_subplans_for_ungrouped_vars_walker(Node *node,
check_subplans_for_ungrouped_vars_context *context);
static int is_single_func(Node *node); static int is_single_func(Node *node);
...@@ -351,11 +359,117 @@ pull_constant_clauses(List *quals, List **constantQual) ...@@ -351,11 +359,117 @@ pull_constant_clauses(List *quals, List **constantQual)
else else
restqual = lcons(lfirst(q), restqual); restqual = lcons(lfirst(q), restqual);
} }
freeList(quals); /* XXX seems a tad risky? */
*constantQual = constqual; *constantQual = constqual;
return restqual; return restqual;
} }
/*
* pull_agg_clause
* Recursively pulls all Aggref nodes from an expression tree.
*
* Returns list of Aggref nodes found. Note the nodes themselves are not
* copied, only referenced.
*/
List *
pull_agg_clause(Node *clause)
{
List *result = NIL;
pull_agg_clause_walker(clause, &result);
return result;
}
static bool
pull_agg_clause_walker(Node *node, List **listptr)
{
if (node == NULL)
return false;
if (IsA(node, Aggref))
{
*listptr = lappend(*listptr, node);
/* continue, to iterate over agg's arg as well (do nested aggregates
* actually work?)
*/
}
return expression_tree_walker(node, pull_agg_clause_walker,
(void *) listptr);
}
/*
* check_subplans_for_ungrouped_vars
* Check for subplans that are being passed ungrouped variables as
* parameters; return TRUE if any are found.
*
* In most contexts, ungrouped variables will be detected by the parser (see
* parse_agg.c, exprIsAggOrGroupCol()). But that routine currently does not
* check subplans, because the necessary info is not computed until the
* planner runs. So we do it here, after we have processed the subplan.
* This ought to be cleaned up someday.
*
* 'clause' is the expression tree to be searched for subplans.
* 'groupClause' is the GROUP BY list (a list of GroupClause nodes).
* 'targetList' is the target list that the group clauses refer to.
*/
bool
check_subplans_for_ungrouped_vars(Node *clause,
List *groupClause,
List *targetList)
{
check_subplans_for_ungrouped_vars_context context;
context.groupClause = groupClause;
context.targetList = targetList;
return check_subplans_for_ungrouped_vars_walker(clause, &context);
}
static bool
check_subplans_for_ungrouped_vars_walker(Node *node,
check_subplans_for_ungrouped_vars_context *context)
{
if (node == NULL)
return false;
/*
* We can ignore Vars other than in subplan args lists,
* since the parser already checked 'em.
*/
if (is_subplan(node))
{
/*
* The args list of the subplan node represents attributes from
* outside passed into the sublink.
*/
List *t;
foreach(t, ((Expr *) node)->args)
{
Node *thisarg = lfirst(t);
bool contained_in_group_clause = false;
List *gl;
foreach(gl, context->groupClause)
{
GroupClause *gcl = lfirst(gl);
Node *groupexpr;
groupexpr = get_sortgroupclause_expr(gcl,
context->targetList);
if (equal(thisarg, groupexpr))
{
contained_in_group_clause = true;
break;
}
}
if (!contained_in_group_clause)
return true; /* found an ungrouped argument */
}
}
return expression_tree_walker(node,
check_subplans_for_ungrouped_vars_walker,
(void *) context);
}
/* /*
* clause_relids_vars * clause_relids_vars
* Retrieves distinct relids and vars appearing within a clause. * Retrieves distinct relids and vars appearing within a clause.
...@@ -416,31 +530,6 @@ NumRelids(Node *clause) ...@@ -416,31 +530,6 @@ NumRelids(Node *clause)
return result; return result;
} }
/*
* fix_opids
* Calculate opid field from opno for each Oper node in given tree.
* (The given tree can be anything expression_tree_walker handles.)
*
* Returns its argument, which has been modified in-place.
*/
List *
fix_opids(List *clauses)
{
/* This tree walk requires no special setup, so away we go... */
fix_opids_walker((Node *) clauses, NULL);
return clauses;
}
static bool
fix_opids_walker (Node *node, void *context)
{
if (node == NULL)
return false;
if (is_opclause(node))
replace_opid((Oper *) ((Expr *) node)->oper);
return expression_tree_walker(node, fix_opids_walker, context);
}
/* /*
* get_relattval * get_relattval
* Extract information from a restriction or join clause for * Extract information from a restriction or join clause for
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.39 1999/08/21 03:49:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.40 1999/08/22 20:14:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include "optimizer/tlist.h" #include "optimizer/tlist.h"
#include "optimizer/var.h" #include "optimizer/var.h"
static Node *unflatten_tlist_mutator(Node *node, List *flat_tlist);
/***************************************************************************** /*****************************************************************************
* ---------- RELATION node target list routines ---------- * ---------- RELATION node target list routines ----------
*****************************************************************************/ *****************************************************************************/
...@@ -28,39 +26,38 @@ static Node *unflatten_tlist_mutator(Node *node, List *flat_tlist); ...@@ -28,39 +26,38 @@ static Node *unflatten_tlist_mutator(Node *node, List *flat_tlist);
/* /*
* tlistentry_member * tlistentry_member
* Finds the (first) member of the given tlist whose expression is * Finds the (first) member of the given tlist whose expression is
* var_equal() to the given var. Result is NULL if no such member. * equal() to the given expression. Result is NULL if no such member.
*/ */
TargetEntry * TargetEntry *
tlistentry_member(Var *var, List *targetlist) tlistentry_member(Node *node, List *targetlist)
{ {
if (var && IsA(var, Var)) List *temp;
foreach(temp, targetlist)
{ {
List *temp; TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
foreach(temp, targetlist) if (equal(node, tlentry->expr))
{ return tlentry;
if (var_equal(var, get_expr(lfirst(temp))))
return (TargetEntry *) lfirst(temp);
}
} }
return NULL; return NULL;
} }
/* /*
* matching_tlist_var * matching_tlist_expr
* Same as tlistentry_member(), except returns the tlist expression * Same as tlistentry_member(), except returns the tlist expression
* rather than its parent TargetEntry node. * rather than its parent TargetEntry node.
*/ */
Expr * Node *
matching_tlist_var(Var *var, List *targetlist) matching_tlist_expr(Node *node, List *targetlist)
{ {
TargetEntry *tlentry; TargetEntry *tlentry;
tlentry = tlistentry_member(var, targetlist); tlentry = tlistentry_member(node, targetlist);
if (tlentry) if (tlentry)
return (Expr *) get_expr(tlentry); return tlentry->expr;
return (Expr *) NULL; return (Node *) NULL;
} }
/* /*
...@@ -69,11 +66,11 @@ matching_tlist_var(Var *var, List *targetlist) ...@@ -69,11 +66,11 @@ matching_tlist_var(Var *var, List *targetlist)
* rather than its parent TargetEntry node. * rather than its parent TargetEntry node.
*/ */
Resdom * Resdom *
tlist_member(Var *var, List *tlist) tlist_member(Node *node, List *targetlist)
{ {
TargetEntry *tlentry; TargetEntry *tlentry;
tlentry = tlistentry_member(var, tlist); tlentry = tlistentry_member(node, targetlist);
if (tlentry) if (tlentry)
return tlentry->resdom; return tlentry->resdom;
...@@ -89,7 +86,7 @@ tlist_member(Var *var, List *tlist) ...@@ -89,7 +86,7 @@ tlist_member(Var *var, List *tlist)
void void
add_var_to_tlist(RelOptInfo *rel, Var *var) add_var_to_tlist(RelOptInfo *rel, Var *var)
{ {
if (! tlistentry_member(var, rel->targetlist)) if (! tlistentry_member((Node *) var, rel->targetlist))
{ {
/* XXX is copyObject necessary here? */ /* XXX is copyObject necessary here? */
rel->targetlist = lappend(rel->targetlist, rel->targetlist = lappend(rel->targetlist,
...@@ -116,84 +113,10 @@ create_tl_element(Var *var, int resdomno) ...@@ -116,84 +113,10 @@ create_tl_element(Var *var, int resdomno)
(Node *) var); (Node *) var);
} }
/*
* get_actual_tlist
* Returns the targetlist elements from a relation tlist.
*
*/
List *
get_actual_tlist(List *tlist)
{
/*
* this function is not making sense. - ay 10/94
*/
#ifdef NOT_USED
List *element = NIL;
List *result = NIL;
if (tlist == NULL)
{
elog(DEBUG, "calling get_actual_tlist with empty tlist");
return NIL;
}
/*
* XXX - it is unclear to me what exactly get_entry should be doing,
* as it is unclear to me the exact relationship between "TL" "TLE"
* and joinlists
*/
foreach(element, tlist)
result = lappend(result, lfirst((List *) lfirst(element)));
return result;
#endif
return tlist;
}
/***************************************************************************** /*****************************************************************************
* ---------- GENERAL target list routines ---------- * ---------- GENERAL target list routines ----------
*****************************************************************************/ *****************************************************************************/
/*
* match_varid
* Searches a target list for an entry matching a given var.
*
* Returns the target list entry (resdom var) of the matching var,
* or NULL if no match.
*/
TargetEntry *
match_varid(Var *test_var, List *tlist)
{
List *tl;
Assert(test_var->varlevelsup == 0); /* XXX why? */
foreach(tl, tlist)
{
TargetEntry *entry = lfirst(tl);
Var *tlvar = get_expr(entry);
if (!IsA(tlvar, Var))
continue;
/*
* we test the original varno, instead of varno which might be
* changed to INNER/OUTER. XXX is test on vartype necessary?
*/
Assert(tlvar->varlevelsup == 0);
if (tlvar->varnoold == test_var->varnoold &&
tlvar->varoattno == test_var->varoattno &&
tlvar->vartype == test_var->vartype)
return entry;
}
return NULL;
}
/* /*
* new_unsorted_tlist * new_unsorted_tlist
* Creates a copy of a target list by creating new resdom nodes * Creates a copy of a target list by creating new resdom nodes
...@@ -220,37 +143,6 @@ new_unsorted_tlist(List *targetlist) ...@@ -220,37 +143,6 @@ new_unsorted_tlist(List *targetlist)
return new_targetlist; return new_targetlist;
} }
/*
* copy_vars
* Replaces the var nodes in the first target list with those from
* the second target list. The two target lists are assumed to be
* identical except their actual resdoms and vars are different.
*
* 'target' is the target list to be replaced
* 'source' is the target list to be copied
*
* Returns a new target list.
*
*/
List *
copy_vars(List *target, List *source)
{
List *result = NIL;
List *src;
List *dest;
for (src = source, dest = target;
src != NIL && dest != NIL;
src = lnext(src), dest = lnext(dest))
{
TargetEntry *temp = makeTargetEntry(((TargetEntry *) lfirst(dest))->resdom,
(Node *) get_expr(lfirst(src)));
result = lappend(result, temp);
}
return result;
}
/* /*
* flatten_tlist * flatten_tlist
* Create a target list that only contains unique variables. * Create a target list that only contains unique variables.
...@@ -292,7 +184,7 @@ add_to_flat_tlist(List *tlist, List *vars) ...@@ -292,7 +184,7 @@ add_to_flat_tlist(List *tlist, List *vars)
{ {
Var *var = lfirst(v); Var *var = lfirst(v);
if (! tlistentry_member(var, tlist)) if (! tlistentry_member((Node *) var, tlist))
{ {
Resdom *r; Resdom *r;
...@@ -310,39 +202,6 @@ add_to_flat_tlist(List *tlist, List *vars) ...@@ -310,39 +202,6 @@ add_to_flat_tlist(List *tlist, List *vars)
return tlist; return tlist;
} }
/*
* unflatten_tlist
* Reconstructs the target list of a query by replacing vars within
* target expressions with vars from the 'flattened' target list.
*
* XXX is this really necessary? Why can't we just use the tlist as is?
*
* 'full_tlist' is the original target list
* 'flat_tlist' is the flattened (var-only) target list
*
* Returns the rebuilt target list. The original is not modified.
*
*/
List *
unflatten_tlist(List *full_tlist, List *flat_tlist)
{
return (List *) unflatten_tlist_mutator((Node *) full_tlist,
flat_tlist);
}
static Node *
unflatten_tlist_mutator(Node *node, List *flat_tlist)
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
return (Node *) get_expr(match_varid((Var *) node,
flat_tlist));
return expression_tree_mutator(node, unflatten_tlist_mutator,
(void *) flat_tlist);
}
Var * Var *
get_expr(TargetEntry *tle) get_expr(TargetEntry *tle)
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.22 1999/08/10 03:00:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.23 1999/08/22 20:14:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -105,29 +105,3 @@ pull_var_clause_walker(Node *node, List **listptr) ...@@ -105,29 +105,3 @@ pull_var_clause_walker(Node *node, List **listptr)
return expression_tree_walker(node, pull_var_clause_walker, return expression_tree_walker(node, pull_var_clause_walker,
(void *) listptr); (void *) listptr);
} }
/*
* var_equal
*
* This is like equal() except that it does NOT test varnoold and
* varoattno. Also, it will not compare non-Var nodes.
*
* Returns t iff two var nodes correspond to the same attribute.
*/
bool
var_equal(Var *var1, Var *var2)
{
if (var1 != NULL && IsA(var1, Var) &&
var2 != NULL && IsA(var2, Var) &&
var1->varno == var2->varno &&
var1->varattno == var2->varattno &&
var1->vartype == var2->vartype &&
var1->vartypmod == var2->vartypmod &&
var1->varlevelsup == var2->varlevelsup)
{
Assert(var1->varlevelsup == 0); /* XXX why do this here??? */
return true;
}
else
return false;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.53 1999/08/21 03:48:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.54 1999/08/22 20:15:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -444,7 +444,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ...@@ -444,7 +444,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/ */
toid = typeTypeId(typenameType(relname)); toid = typeTypeId(typenameType(relname));
/* replace it in the arg list */ /* replace it in the arg list */
lfirst(fargs) = makeVar(vnum, 0, toid, -1, 0, vnum, 0); lfirst(fargs) = makeVar(vnum, 0, toid, -1, 0);
} }
else if (!attisset) else if (!attisset)
{ /* set functions don't have parameters */ { /* set functions don't have parameters */
...@@ -1300,7 +1300,7 @@ setup_tlist(char *attname, Oid relid) ...@@ -1300,7 +1300,7 @@ setup_tlist(char *attname, Oid relid)
0, 0,
InvalidOid, InvalidOid,
false); false);
varnode = makeVar(-1, attno, typeid, type_mod, 0, -1, attno); varnode = makeVar(-1, attno, typeid, type_mod, 0);
tle = makeTargetEntry(resnode, (Node *) varnode); tle = makeTargetEntry(resnode, (Node *) varnode);
return lcons(tle, NIL); return lcons(tle, NIL);
...@@ -1325,7 +1325,7 @@ setup_base_tlist(Oid typeid) ...@@ -1325,7 +1325,7 @@ setup_base_tlist(Oid typeid)
0, 0,
InvalidOid, InvalidOid,
false); false);
varnode = makeVar(-1, 1, typeid, -1, 0, -1, 1); varnode = makeVar(-1, 1, typeid, -1, 0);
tle = makeTargetEntry(resnode, (Node *) varnode); tle = makeTargetEntry(resnode, (Node *) varnode);
return lcons(tle, NIL); return lcons(tle, NIL);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.29 1999/07/19 00:26:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.30 1999/08/22 20:15:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -216,8 +216,7 @@ make_var(ParseState *pstate, Oid relid, char *refname, ...@@ -216,8 +216,7 @@ make_var(ParseState *pstate, Oid relid, char *refname,
vartypeid = get_atttype(relid, attid); vartypeid = get_atttype(relid, attid);
type_mod = get_atttypmod(relid, attid); type_mod = get_atttypmod(relid, attid);
varnode = makeVar(vnum, attid, vartypeid, type_mod, varnode = makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
sublevels_up, vnum, attid);
return varnode; return varnode;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: makefuncs.h,v 1.20 1999/07/15 23:03:52 momjian Exp $ * $Id: makefuncs.h,v 1.21 1999/08/22 20:15:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,9 +25,7 @@ extern Var *makeVar(Index varno, ...@@ -25,9 +25,7 @@ extern Var *makeVar(Index varno,
AttrNumber varattno, AttrNumber varattno,
Oid vartype, Oid vartype,
int32 vartypmod, int32 vartypmod,
Index varlevelsup, Index varlevelsup);
Index varnoold,
AttrNumber varoattno);
extern TargetEntry *makeTargetEntry(Resdom *resdom, Node *expr); extern TargetEntry *makeTargetEntry(Resdom *resdom, Node *expr);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: primnodes.h,v 1.34 1999/08/21 03:49:09 tgl Exp $ * $Id: primnodes.h,v 1.35 1999/08/22 20:15:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -120,15 +120,23 @@ typedef struct Expr ...@@ -120,15 +120,23 @@ typedef struct Expr
/* ---------------- /* ----------------
* Var * Var
* varno - index of this var's relation in the range table * varno - index of this var's relation in the range table
* (could be INNER or OUTER) * (could also be INNER or OUTER)
* varattno - attribute number of this var, or zero for all * varattno - attribute number of this var, or zero for all
* vartype - pg_type tuple oid for the type of this var * vartype - pg_type tuple OID for the type of this var
* vartypmod - pg_attribute typmod value * vartypmod - pg_attribute typmod value
* varlevelsup - for subquery variables referencing outer relations * varlevelsup - for subquery variables referencing outer relations;
* varnoold - keep varno around in case it got changed to INNER/ * 0 in a normal var, >0 means N levels up
* OUTER (see match_varid) * varnoold - original value of varno
* varoattno - attribute number of this var * varoattno - original value of varattno
* [ '(varnoold varoattno) was varid -ay 2/95] *
* Note: during parsing/planning, varnoold/varoattno are always just copies
* of varno/varattno. At the tail end of planning, Var nodes appearing in
* upper-level plan nodes are reassigned to point to the outputs of their
* subplans; for example, in a join node varno becomes INNER or OUTER and
* varattno becomes the index of the proper element of that subplan's target
* list. But varnoold/varoattno continue to hold the original values.
* The code doesn't really need varnoold/varoattno, but they are very useful
* for debugging and interpreting completed plans, so we keep them around.
* ---------------- * ----------------
*/ */
#define INNER 65000 #define INNER 65000
...@@ -145,8 +153,8 @@ typedef struct Var ...@@ -145,8 +153,8 @@ typedef struct Var
Oid vartype; Oid vartype;
int32 vartypmod; int32 vartypmod;
Index varlevelsup; /* erased by upper optimizer */ Index varlevelsup; /* erased by upper optimizer */
Index varnoold; /* only used by optimizer */ Index varnoold; /* mainly for debugging --- see above */
AttrNumber varoattno; /* only used by optimizer */ AttrNumber varoattno;
} Var; } Var;
/* ---------------- /* ----------------
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: clauses.h,v 1.28 1999/08/16 02:17:44 tgl Exp $ * $Id: clauses.h,v 1.29 1999/08/22 20:14:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -38,9 +38,13 @@ extern Expr *make_ands_explicit(List *andclauses); ...@@ -38,9 +38,13 @@ extern Expr *make_ands_explicit(List *andclauses);
extern List *make_ands_implicit(Expr *clause); extern List *make_ands_implicit(Expr *clause);
extern List *pull_constant_clauses(List *quals, List **constantQual); extern List *pull_constant_clauses(List *quals, List **constantQual);
extern List *pull_agg_clause(Node *clause);
extern bool check_subplans_for_ungrouped_vars(Node *clause,
List *groupClause,
List *targetList);
extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars); extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars);
extern int NumRelids(Node *clause); extern int NumRelids(Node *clause);
extern List *fix_opids(List *clauses);
extern void get_relattval(Node *clause, int targetrelid, extern void get_relattval(Node *clause, int targetrelid,
int *relid, AttrNumber *attno, int *relid, AttrNumber *attno,
Datum *constval, int *flag); Datum *constval, int *flag);
...@@ -53,8 +57,8 @@ extern bool expression_tree_walker(Node *node, bool (*walker) (), ...@@ -53,8 +57,8 @@ extern bool expression_tree_walker(Node *node, bool (*walker) (),
extern Node *expression_tree_mutator(Node *node, Node * (*mutator) (), extern Node *expression_tree_mutator(Node *node, Node * (*mutator) (),
void *context); void *context);
#define is_subplan(clause) ((Node*) (clause) != NULL && \ #define is_subplan(clause) ((clause) != NULL && \
nodeTag((Node*) (clause)) == T_Expr && \ IsA(clause, Expr) && \
((Expr *) (clause))->opType == SUBPLAN_EXPR) ((Expr *) (clause))->opType == SUBPLAN_EXPR)
#endif /* CLAUSES_H */ #endif /* CLAUSES_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: planmain.h,v 1.31 1999/08/21 03:49:15 tgl Exp $ * $Id: planmain.h,v 1.32 1999/08/22 20:14:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,14 +27,14 @@ extern Plan *query_planner(Query *root, ...@@ -27,14 +27,14 @@ extern Plan *query_planner(Query *root,
* prototypes for plan/createplan.c * prototypes for plan/createplan.c
*/ */
extern Plan *create_plan(Path *best_path); extern Plan *create_plan(Path *best_path);
extern SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid, extern SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
Plan *lefttree);
extern Sort *make_sort(List *tlist, Oid nonameid, Plan *lefttree, extern Sort *make_sort(List *tlist, Oid nonameid, Plan *lefttree,
int keycount); int keycount);
extern Agg *make_agg(List *tlist, Plan *lefttree); extern Agg *make_agg(List *tlist, Plan *lefttree);
extern Group *make_group(List *tlist, bool tuplePerGroup, int ngrp, extern Group *make_group(List *tlist, bool tuplePerGroup, int ngrp,
AttrNumber *grpColIdx, Plan *lefttree); AttrNumber *grpColIdx, Plan *lefttree);
extern Unique *make_unique(List *tlist, Plan *lefttree, char *uniqueAttr); extern Unique *make_unique(List *tlist, Plan *lefttree, char *uniqueAttr);
extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
/* /*
* prototypes for plan/initsplan.c * prototypes for plan/initsplan.c
...@@ -47,17 +47,10 @@ extern void add_missing_vars_to_tlist(Query *root, List *tlist); ...@@ -47,17 +47,10 @@ extern void add_missing_vars_to_tlist(Query *root, List *tlist);
/* /*
* prototypes for plan/setrefs.c * prototypes for plan/setrefs.c
*/ */
extern void set_tlist_references(Plan *plan); extern void set_plan_references(Plan *plan);
extern List *join_references(List *clauses, List *outer_tlist, extern List *join_references(List *clauses, List *outer_tlist,
List *inner_tlist); List *inner_tlist, Index acceptable_rel);
extern void replace_tlist_with_subplan_refs(List *tlist, extern void fix_opids(Node *node);
Index subvarno,
List *subplanTargetList);
extern bool set_agg_tlist_references(Agg *aggNode);
extern List *pull_agg_clause(Node *clause);
extern void check_having_for_ungrouped_vars(Node *clause,
List *groupClause,
List *targetList);
/* /*
* prep/prepkeyset.c * prep/prepkeyset.c
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: tlist.h,v 1.21 1999/08/21 03:49:15 tgl Exp $ * $Id: tlist.h,v 1.22 1999/08/22 20:14:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,20 +15,16 @@ ...@@ -15,20 +15,16 @@
#include "nodes/relation.h" #include "nodes/relation.h"
extern TargetEntry *tlistentry_member(Var *var, List *targetlist); extern TargetEntry *tlistentry_member(Node *node, List *targetlist);
extern Expr *matching_tlist_var(Var *var, List *targetlist); extern Node *matching_tlist_expr(Node *node, List *targetlist);
extern Resdom *tlist_member(Node *node, List *targetlist);
extern void add_var_to_tlist(RelOptInfo *rel, Var *var); extern void add_var_to_tlist(RelOptInfo *rel, Var *var);
extern TargetEntry *create_tl_element(Var *var, int resdomno); extern TargetEntry *create_tl_element(Var *var, int resdomno);
extern List *get_actual_tlist(List *tlist);
extern Resdom *tlist_member(Var *var, List *tlist);
extern TargetEntry *match_varid(Var *test_var, List *tlist);
extern List *new_unsorted_tlist(List *targetlist); extern List *new_unsorted_tlist(List *targetlist);
extern List *copy_vars(List *target, List *source);
extern List *flatten_tlist(List *tlist); extern List *flatten_tlist(List *tlist);
extern List *add_to_flat_tlist(List *tlist, List *vars); extern List *add_to_flat_tlist(List *tlist, List *vars);
extern List *unflatten_tlist(List *full_tlist,
List *flat_tlist);
extern Var *get_expr(TargetEntry *tle); extern Var *get_expr(TargetEntry *tle);
extern Node *get_sortgroupclause_expr(SortClause *sortClause, extern Node *get_sortgroupclause_expr(SortClause *sortClause,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: var.h,v 1.8 1999/07/15 15:21:23 momjian Exp $ * $Id: var.h,v 1.9 1999/08/22 20:14:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,6 +18,5 @@ ...@@ -18,6 +18,5 @@
extern List *pull_varnos(Node *me); extern List *pull_varnos(Node *me);
extern bool contain_var_clause(Node *clause); extern bool contain_var_clause(Node *clause);
extern List *pull_var_clause(Node *clause); extern List *pull_var_clause(Node *clause);
extern bool var_equal(Var *var1, Var *var2);
#endif /* VAR_H */ #endif /* VAR_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment