diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 08ed6a7316341f4e19d4684f052b4bfa118186d4..1971ccb9282faedacfac42c33768e2a7a89ffeb9 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.35 1999/07/24 23:21:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.36 1999/08/10 03:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,28 +51,29 @@ static Oid hashjoinop(Expr *clause); void make_var_only_tlist(Query *root, List *tlist) { - List *tlist_vars = NIL; - List *l = NIL; - List *tvar = NIL; + List *tlist_vars = pull_var_clause((Node *) tlist); - foreach(l, tlist) - { - TargetEntry *entry = (TargetEntry *) lfirst(l); + add_vars_to_targetlist(root, tlist_vars); + freeList(tlist_vars); +} - tlist_vars = nconc(tlist_vars, pull_var_clause(entry->expr)); - } +/* + * add_vars_to_targetlist + * For each variable appearing in the list, add it to the relation's + * targetlist if not already present. Rel nodes will also be created + * if not already present. + */ +static void +add_vars_to_targetlist(Query *root, List *vars) +{ + List *temp; - /* now, the target list only contains Var nodes */ - foreach(tvar, tlist_vars) + foreach(temp, vars) { - Var *var = (Var *) lfirst(tvar); - Index varno; - RelOptInfo *result; - - varno = var->varno; - result = get_base_rel(root, varno); + Var *var = (Var *) lfirst(temp); + RelOptInfo *rel = get_base_rel(root, var->varno); - add_var_to_tlist(result, var); + add_var_to_tlist(rel, var); } } @@ -87,31 +88,30 @@ make_var_only_tlist(Query *root, List *tlist) void add_missing_vars_to_tlist(Query *root, List *tlist) { + int varno = 1; List *l; - int varno; - varno = 1; foreach(l, root->rtable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); Relids relids; - RelOptInfo *result; - Var *var; relids = lconsi(varno, NIL); if (rte->inFromCl && !rel_member(relids, root->base_rel_list)) { + RelOptInfo *rel; + Var *var; + + /* add it to base_rel_list */ + rel = get_base_rel(root, varno); + /* give it a dummy tlist entry for its OID */ var = makeVar(varno, ObjectIdAttributeNumber, OIDOID, -1, 0, varno, ObjectIdAttributeNumber); - /* add it to base_rel_list */ - result = get_base_rel(root, varno); - add_var_to_tlist(result, var); + add_var_to_tlist(rel, var); } pfree(relids); varno++; } - - return; } /***************************************************************************** @@ -239,26 +239,6 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo, } } -/* - * add_vars_to_targetlist - * For each variable appearing in a clause, add it to the relation's - * targetlist if not already present. - */ -static void -add_vars_to_targetlist(Query *root, List *vars) -{ - List *temp; - - foreach(temp, vars) - { - Var *var = (Var *) lfirst(temp); - RelOptInfo *rel = get_base_rel(root, var->varno); - - if (tlistentry_member(var, rel->targetlist) == NULL) - add_var_to_tlist(rel, var); - } -} - /***************************************************************************** * * JOININFO @@ -269,7 +249,7 @@ add_vars_to_targetlist(Query *root, List *vars) * 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 + * each restrictinfo node (within a joininfo node) for all relations in a * query. * * Returns nothing. @@ -277,43 +257,43 @@ add_vars_to_targetlist(Query *root, List *vars) void set_joininfo_mergeable_hashable(List *rel_list) { - List *x, - *y, - *z; - RelOptInfo *rel; - JoinInfo *joininfo; - RestrictInfo *restrictinfo; - Expr *clause; + List *x; foreach(x, rel_list) { - rel = (RelOptInfo *) lfirst(x); + RelOptInfo *rel = (RelOptInfo *) lfirst(x); + List *y; + foreach(y, rel->joininfo) { - joininfo = (JoinInfo *) lfirst(y); + JoinInfo *joininfo = (JoinInfo *) lfirst(y); + List *z; + foreach(z, joininfo->jinfo_restrictinfo) { - restrictinfo = (RestrictInfo *) lfirst(z); - clause = restrictinfo->clause; + RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(z); + Expr *clause = restrictinfo->clause; + if (is_joinable((Node *) clause)) { - MergeOrder *sortop = (MergeOrder *) NULL; - Oid hashop = (Oid) NULL; - if (_enable_mergejoin_) - sortop = mergejoinop(clause); - if (sortop) { - restrictinfo->mergejoinorder = sortop; - joininfo->mergejoinable = true; + MergeOrder *sortop = mergejoinop(clause); + if (sortop) + { + restrictinfo->mergejoinorder = sortop; + joininfo->mergejoinable = true; + } } if (_enable_hashjoin_) - hashop = hashjoinop(clause); - if (hashop) { - restrictinfo->hashjoinoperator = hashop; - joininfo->hashjoinable = true; + Oid hashop = hashjoinop(clause); + if (hashop) + { + restrictinfo->hashjoinoperator = hashop; + joininfo->hashjoinable = true; + } } } } @@ -323,8 +303,8 @@ set_joininfo_mergeable_hashable(List *rel_list) /* * mergejoinop - * Returns the mergejoin operator of an operator iff 'clause' is - * mergejoinable, i.e., both operands are single vars and the operator is + * Returns a MergeOrder node for 'clause' iff 'clause' is mergejoinable, + * i.e., both operands are single vars and the operator is * a mergejoinable operator. */ static MergeOrder * @@ -346,7 +326,7 @@ mergejoinop(Expr *clause) /* caution: is_opclause accepts more than I do, so check it */ if (!right) return NULL; /* unary opclauses need not apply */ - if (!IsA(left, Var) ||!IsA(right, Var)) + if (!IsA(left, Var) || !IsA(right, Var)) return NULL; opno = ((Oper *) clause->oper)->opno; @@ -374,8 +354,8 @@ mergejoinop(Expr *clause) /* * hashjoinop - * Returns the hashjoin operator of an operator iff 'clause' is - * hashjoinable, i.e., both operands are single vars and the operator is + * Returns the hashjoin operator iff 'clause' is hashjoinable, + * i.e., both operands are single vars and the operator is * a hashjoinable operator. */ static Oid @@ -393,7 +373,7 @@ hashjoinop(Expr *clause) /* caution: is_opclause accepts more than I do, so check it */ if (!right) return InvalidOid; /* unary opclauses need not apply */ - if (!IsA(left, Var) ||!IsA(right, Var)) + if (!IsA(left, Var) || !IsA(right, Var)) return InvalidOid; return op_hashjoinable(((Oper *) clause->oper)->opno, diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 7bc70bd22c4bee76320e6871ed5d05a8cae553d8..322aeba1ce3db5bce5d257d92329dfb21973401e 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.44 1999/08/09 00:51:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.45 1999/08/10 03:00:15 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -78,7 +78,8 @@ bool is_opclause(Node *clause) { return (clause != NULL && - nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == OP_EXPR); + IsA(clause, Expr) && + ((Expr *) clause)->opType == OP_EXPR); } /* @@ -147,7 +148,7 @@ bool is_funcclause(Node *clause) { return (clause != NULL && - nodeTag(clause) == T_Expr && + IsA(clause, Expr) && ((Expr *) clause)->opType == FUNC_EXPR); } @@ -183,9 +184,9 @@ make_funcclause(Func *func, List *funcargs) bool or_clause(Node *clause) { - return clause != NULL && - nodeTag(clause) == T_Expr && - ((Expr *) clause)->opType == OR_EXPR; + return (clause != NULL && + IsA(clause, Expr) && + ((Expr *) clause)->opType == OR_EXPR); } /* @@ -220,7 +221,7 @@ bool not_clause(Node *clause) { return (clause != NULL && - nodeTag(clause) == T_Expr && + IsA(clause, Expr) && ((Expr *) clause)->opType == NOT_EXPR); } @@ -269,7 +270,7 @@ bool and_clause(Node *clause) { return (clause != NULL && - nodeTag(clause) == T_Expr && + IsA(clause, Expr) && ((Expr *) clause)->opType == AND_EXPR); } @@ -319,27 +320,10 @@ make_ands_implicit(Expr *clause) return lcons(clause, NIL); } -/***************************************************************************** - * CASE clause functions - *****************************************************************************/ - - -/* - * case_clause - * - * Returns t iff its argument is a 'case' clause: (CASE { expr }). - * - */ -bool -case_clause(Node *clause) -{ - return (clause != NULL && - nodeTag(clause) == T_CaseExpr); -} /***************************************************************************** * * - * * + * General clause-manipulating routines * * * *****************************************************************************/ @@ -374,20 +358,21 @@ pull_constant_clauses(List *quals, List **constantQual) /* * clause_relids_vars - * Retrieves relids and vars appearing within a clause. - * Returns ((relid1 relid2 ... relidn) (var1 var2 ... varm)) where - * vars appear in the clause this is done by recursively searching - * through the left and right operands of a clause. - * - * Returns the list of relids and vars. + * Retrieves distinct relids and vars appearing within a clause. * + * '*relids' is set to an integer list of all distinct "varno"s appearing + * in Vars within the clause. + * '*vars' is set to a list of all distinct Vars appearing within the clause. + * Var nodes are considered distinct if they have different varno + * or varattno values. If there are several occurrences of the same + * varno/varattno, you get a randomly chosen one... */ void clause_get_relids_vars(Node *clause, Relids *relids, List **vars) { List *clvars = pull_var_clause(clause); - List *var_list = NIL; List *varno_list = NIL; + List *var_list = NIL; List *i; foreach(i, clvars) @@ -397,7 +382,7 @@ clause_get_relids_vars(Node *clause, Relids *relids, List **vars) Assert(var->varlevelsup == 0); if (!intMember(var->varno, varno_list)) - varno_list = lappendi(varno_list, var->varno); + varno_list = lconsi(var->varno, varno_list); foreach(vi, var_list) { Var *in_list = (Var *) lfirst(vi); @@ -407,7 +392,7 @@ clause_get_relids_vars(Node *clause, Relids *relids, List **vars) break; } if (vi == NIL) - var_list = lappend(var_list, var); + var_list = lcons(var, var_list); } freeList(clvars); @@ -424,22 +409,10 @@ clause_get_relids_vars(Node *clause, Relids *relids, List **vars) int NumRelids(Node *clause) { - List *vars = pull_var_clause(clause); - List *var_list = NIL; - List *i; - int result; + List *varno_list = pull_varnos(clause); + int result = length(varno_list); - foreach(i, vars) - { - Var *var = (Var *) lfirst(i); - - if (!intMember(var->varno, var_list)) - var_list = lconsi(var->varno, var_list); - } - - result = length(var_list); - freeList(vars); - freeList(var_list); + freeList(varno_list); return result; } @@ -468,7 +441,7 @@ is_joinable(Node *clause) * One side of the clause (i.e. left or right operands) must either be * a var node ... */ - if (IsA(leftop, Var) ||IsA(rightop, Var)) + if (IsA(leftop, Var) || IsA(rightop, Var)) return true; /* @@ -480,36 +453,6 @@ is_joinable(Node *clause) return false; } -/* - * qual_clause_p - * - * Returns t iff 'clause' is a valid qualification clause. - * - * For now we accept only "var op const" or "const op var". - */ -bool -qual_clause_p(Node *clause) -{ - Node *leftop, - *rightop; - - if (!is_opclause(clause)) - return false; - - leftop = (Node *) get_leftop((Expr *) clause); - rightop = (Node *) get_rightop((Expr *) clause); - - if (!rightop) - return false; /* unary opclauses need not apply */ - - /* How about Param-s ? - vadim 02/03/98 */ - if (IsA(leftop, Var) &&IsA(rightop, Const)) - return true; - if (IsA(rightop, Var) &&IsA(leftop, Const)) - return true; - return false; -} - /* * fix_opids * Calculate opid field from opno for each Oper node in given tree. @@ -644,24 +587,16 @@ static int is_single_func(Node *node) { if (is_funcclause(node)) { - List *vars = pull_var_clause(node); + List *varnos = pull_varnos(node); - if (vars != NIL) + if (length(varnos) == 1) { - int funcvarno = ((Var *) lfirst(vars))->varno; - List *v; - /* need to check that all args of func are same relation */ - foreach(v, lnext(vars)) - { - if (((Var *) lfirst(v))->varno != funcvarno) - { - funcvarno = 0; - break; - } - } - freeList(vars); + int funcvarno = lfirsti(varnos); + + freeList(varnos); return funcvarno; } + freeList(varnos); } return 0; } diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 386f23dba85c9fd778e534d672c3286334f245c2..921bb1d671a2627fa9760550b373dd166ca1eb2f 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.37 1999/08/09 05:34:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.38 1999/08/10 03:00:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -285,37 +285,31 @@ copy_vars(List *target, List *source) List * flatten_tlist(List *tlist) { + List *vlist = pull_var_clause((Node *) tlist); int last_resdomno = 1; List *new_tlist = NIL; - List *tl; + List *v; - foreach(tl, tlist) + foreach(v, vlist) { - TargetEntry *tl_entry = (TargetEntry *) lfirst(tl); - List *vlist = pull_var_clause((Node *) get_expr(tl_entry)); - List *v; + Var *var = lfirst(v); - foreach(v, vlist) + if (! tlistentry_member(var, new_tlist)) { - Var *var = lfirst(v); - - if (! tlistentry_member(var, new_tlist)) - { - Resdom *r; - - r = makeResdom(last_resdomno++, - var->vartype, - var->vartypmod, - NULL, - (Index) 0, - (Oid) 0, - false); - new_tlist = lappend(new_tlist, - makeTargetEntry(r, (Node *) var)); - } + Resdom *r; + + r = makeResdom(last_resdomno++, + var->vartype, + var->vartypmod, + NULL, + (Index) 0, + (Oid) 0, + false); + new_tlist = lappend(new_tlist, + makeTargetEntry(r, (Node *) var)); } - freeList(vlist); } + freeList(vlist); return new_tlist; } @@ -334,20 +328,8 @@ flatten_tlist(List *tlist) List * flatten_tlist_vars(List *full_tlist, List *flat_tlist) { - List *result = NIL; - List *x; - - foreach(x, full_tlist) - { - TargetEntry *tle = lfirst(x); - - result = lappend(result, - makeTargetEntry(tle->resdom, - flatten_tlist_vars_mutator((Node *) get_expr(tle), - flat_tlist))); - } - - return result; + return (List *) flatten_tlist_vars_mutator((Node *) full_tlist, + flat_tlist); } static Node * diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 5e3ea9e492d9428e7450405896e99cc81955b20e..be181ea626f2bce9d8826359700eb6a6bd6ee006 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.21 1999/07/15 22:39:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.22 1999/08/10 03:00:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,12 +15,10 @@ #include "postgres.h" - #include "optimizer/clauses.h" #include "optimizer/var.h" - static bool pull_varnos_walker(Node *node, List **listptr); static bool contain_var_clause_walker(Node *node, void *context); static bool pull_var_clause_walker(Node *node, List **listptr); @@ -111,22 +109,23 @@ pull_var_clause_walker(Node *node, List **listptr) /* * var_equal * - * The only difference between this an equal() is that this does not - * test varnoold and varoattno. + * 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 (IsA(var1, Var) &&IsA(var2, Var) && - (((Var *) var1)->varno == ((Var *) var2)->varno) && - (((Var *) var1)->vartype == ((Var *) var2)->vartype) && - (((Var *) var1)->vartypmod == ((Var *) var2)->vartypmod) && - (((Var *) var1)->varlevelsup == ((Var *) var2)->varlevelsup) && - (((Var *) var1)->varattno == ((Var *) var2)->varattno)) + 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(((Var *) var1)->varlevelsup == 0); + Assert(var1->varlevelsup == 0); /* XXX why do this here??? */ return true; } else diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 9fa4ff245ce72eb280fb8c81652a963121e15c9b..3ebf442791222c9f6a83d7f6a34fc8e1c2ee3d80 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: clauses.h,v 1.25 1999/08/09 00:51:23 tgl Exp $ + * $Id: clauses.h,v 1.26 1999/08/10 03:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,13 +37,10 @@ extern Expr *make_andclause(List *andclauses); extern Expr *make_ands_explicit(List *andclauses); extern List *make_ands_implicit(Expr *clause); -extern bool case_clause(Node *clause); - extern List *pull_constant_clauses(List *quals, List **constantQual); extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars); extern int NumRelids(Node *clause); extern bool is_joinable(Node *clause); -extern bool qual_clause_p(Node *clause); extern List *fix_opids(List *clauses); extern void get_relattval(Node *clause, int targetrelid, int *relid, AttrNumber *attno,