diff options
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 579 |
1 files changed, 303 insertions, 276 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 35b3969b702..62ff23f207e 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * initsplan.c-- - * Target list, qualification, joininfo initialization routines + * Target list, qualification, joininfo initialization routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.5 1997/04/24 16:04:23 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.6 1997/09/07 04:44:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,370 +33,397 @@ #include "optimizer/clauses.h" #include "optimizer/cost.h" -extern int Quiet; +extern int Quiet; -static void add_clause_to_rels(Query *root, List *clause); -static void add_join_clause_info_to_rels(Query *root, CInfo *clauseinfo, - List *join_relids); -static void add_vars_to_rels(Query *root, List *vars, List *join_relids); +static void add_clause_to_rels(Query * root, List * clause); +static void +add_join_clause_info_to_rels(Query * root, CInfo * clauseinfo, + List * join_relids); +static void add_vars_to_rels(Query * root, List * vars, List * join_relids); -static MergeOrder *mergesortop(Expr *clause); -static Oid hashjoinop(Expr *clause); +static MergeOrder *mergesortop(Expr * clause); +static Oid hashjoinop(Expr * clause); /***************************************************************************** * - * TARGET LISTS + * TARGET LISTS * *****************************************************************************/ -/* +/* * initialize_rel_nodes-- - * Creates rel nodes for every relation mentioned in the target list - * 'tlist' (if a node hasn't already been created) and adds them to - * *query-relation-list*. Creates targetlist entries for each member of - * 'tlist' and adds them to the tlist field of the appropriate rel node. - * - * Returns nothing. + * Creates rel nodes for every relation mentioned in the target list + * 'tlist' (if a node hasn't already been created) and adds them to + * *query-relation-list*. Creates targetlist entries for each member of + * 'tlist' and adds them to the tlist field of the appropriate rel node. + * + * Returns nothing. */ void -initialize_base_rels_list(Query *root, List *tlist) +initialize_base_rels_list(Query * root, List * tlist) { - List *tlist_vars = NIL; - List *l = NIL; - List *tvar = NIL; - - foreach (l, tlist) { - TargetEntry *entry = (TargetEntry *) lfirst(l); - - tlist_vars = append(tlist_vars, pull_var_clause(entry->expr)); - } - - /* now, the target list only contains Var nodes */ - foreach (tvar, tlist_vars) { - Var *var; - Index varno; - Rel *result; - - var = (Var*)lfirst(tvar); - varno = var->varno; - result = get_base_rel(root, varno); - - add_tl_element(result, var); - } + List *tlist_vars = NIL; + List *l = NIL; + List *tvar = NIL; + + foreach(l, tlist) + { + TargetEntry *entry = (TargetEntry *) lfirst(l); + + tlist_vars = append(tlist_vars, pull_var_clause(entry->expr)); + } + + /* now, the target list only contains Var nodes */ + foreach(tvar, tlist_vars) + { + Var *var; + Index varno; + Rel *result; + + var = (Var *) lfirst(tvar); + varno = var->varno; + result = get_base_rel(root, varno); + + add_tl_element(result, var); + } } /* * add_missing_variables_to_base_rels - - * If we have range variable(s) in the FROM clause that does not appear - * in the target list nor qualifications, we add it to the base relation - * list. For instance, "select f.x from foo f, foo f2" is a join of f and - * f2. Note that if we have "select foo.x from foo f", it also gets turned - * into a join. + * If we have range variable(s) in the FROM clause that does not appear + * in the target list nor qualifications, we add it to the base relation + * list. For instance, "select f.x from foo f, foo f2" is a join of f and + * f2. Note that if we have "select foo.x from foo f", it also gets turned + * into a join. */ void -add_missing_vars_to_base_rels(Query *root, List *tlist) +add_missing_vars_to_base_rels(Query * root, List * tlist) { - List *l; - int varno; - - varno = 1; - foreach (l, root->rtable) { - RangeTblEntry *rte = (RangeTblEntry *)lfirst(l); - List *relids; - Rel *result; - Var *var; - - relids = lconsi(varno, NIL); - if (rte->inFromCl && - !rel_member(relids, root->base_relation_list_)) { - - var = makeVar(varno, -2 , 26, varno, -2); - /* add it to base_relation_list_ */ - result = get_base_rel(root, varno); - add_tl_element(result, var); + List *l; + int varno; + + varno = 1; + foreach(l, root->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); + List *relids; + Rel *result; + Var *var; + + relids = lconsi(varno, NIL); + if (rte->inFromCl && + !rel_member(relids, root->base_relation_list_)) + { + + var = makeVar(varno, -2, 26, varno, -2); + /* add it to base_relation_list_ */ + result = get_base_rel(root, varno); + add_tl_element(result, var); + } + pfree(relids); + varno++; } - pfree(relids); - varno++; - } - return; + return; } /***************************************************************************** * - * QUALIFICATIONS + * QUALIFICATIONS * *****************************************************************************/ -/* +/* * initialize-qualification-- - * Initializes ClauseInfo and JoinInfo fields of relation entries for all - * relations appearing within clauses. Creates new relation entries if - * necessary, adding them to *query-relation-list*. - * - * Returns nothing of interest. + * Initializes ClauseInfo and JoinInfo fields of relation entries for all + * relations appearing within clauses. Creates new relation entries if + * necessary, adding them to *query-relation-list*. + * + * Returns nothing of interest. */ void -initialize_base_rels_jinfo(Query *root, List *clauses) +initialize_base_rels_jinfo(Query * root, List * clauses) { - List *clause; + List *clause; - foreach (clause, clauses) { - add_clause_to_rels(root, lfirst(clause)); - } - return; + foreach(clause, clauses) + { + add_clause_to_rels(root, lfirst(clause)); + } + return; } -/* +/* * add-clause-to-rels-- - * Add clause information to either the 'ClauseInfo' or 'JoinInfo' field - * of a relation entry(depending on whether or not the clause is a join) - * by creating a new ClauseInfo node and setting appropriate fields - * within the nodes. - * - * Returns nothing of interest. + * Add clause information to either the 'ClauseInfo' or 'JoinInfo' field + * of a relation entry(depending on whether or not the clause is a join) + * by creating a new ClauseInfo node and setting appropriate fields + * within the nodes. + * + * Returns nothing of interest. */ static void -add_clause_to_rels(Query *root, List *clause) +add_clause_to_rels(Query * root, List * clause) { - List *relids; - List *vars; - CInfo *clauseinfo = makeNode(CInfo); + List *relids; + List *vars; + CInfo *clauseinfo = makeNode(CInfo); - /* - * Retrieve all relids and vars contained within the clause. - */ - clause_relids_vars((Node*)clause, &relids, &vars); + /* + * Retrieve all relids and vars contained within the clause. + */ + clause_relids_vars((Node *) clause, &relids, &vars); - clauseinfo->clause = (Expr*)clause; - clauseinfo->notclause = contains_not((Node*)clause); - clauseinfo->selectivity = 0; - clauseinfo->indexids = NIL; - clauseinfo->mergesortorder = (MergeOrder*)NULL; - clauseinfo->hashjoinoperator = (Oid)0; - + clauseinfo->clause = (Expr *) clause; + clauseinfo->notclause = contains_not((Node *) clause); + clauseinfo->selectivity = 0; + clauseinfo->indexids = NIL; + clauseinfo->mergesortorder = (MergeOrder *) NULL; + clauseinfo->hashjoinoperator = (Oid) 0; - if(length(relids) == 1) { - Rel *rel = get_base_rel(root, lfirsti(relids)); - - /* - * There is only one relation participating in 'clause', - * so 'clause' must be a restriction clause. - */ - /* the selectivity of the clause must be computed - regardless of whether it's a restriction or a join clause */ - if (is_funcclause((Node*)clause)) - { + if (length(relids) == 1) + { + Rel *rel = get_base_rel(root, lfirsti(relids)); + /* - * XXX If we have a func clause set selectivity to 1/3, - * really need a true selectivity function. + * There is only one relation participating in 'clause', so + * 'clause' must be a restriction clause. */ - clauseinfo->selectivity = (Cost)0.3333333; - } - else - { - clauseinfo->selectivity = - compute_clause_selec(root, (Node*)clause, - NIL); - } - rel->clauseinfo = lcons(clauseinfo, - rel->clauseinfo); - } else { - /* - * 'clause' is a join clause, since there is more than one - * atom in the relid list. - */ - - if (is_funcclause((Node*)clause)) - { + /* - * XXX If we have a func clause set selectivity to 1/3, - * really need a true selectivity function. + * the selectivity of the clause must be computed regardless of + * whether it's a restriction or a join clause */ - clauseinfo->selectivity = (Cost)0.3333333; - } + if (is_funcclause((Node *) clause)) + { + + /* + * XXX If we have a func clause set selectivity to 1/3, really + * need a true selectivity function. + */ + clauseinfo->selectivity = (Cost) 0.3333333; + } + else + { + clauseinfo->selectivity = + compute_clause_selec(root, (Node *) clause, + NIL); + } + rel->clauseinfo = lcons(clauseinfo, + rel->clauseinfo); + } else - { - clauseinfo->selectivity = - compute_clause_selec(root, (Node*)clause, - NIL); - } - add_join_clause_info_to_rels(root, clauseinfo, relids); - add_vars_to_rels(root,vars, relids); - } + { + + /* + * 'clause' is a join clause, since there is more than one atom in + * the relid list. + */ + + if (is_funcclause((Node *) clause)) + { + + /* + * XXX If we have a func clause set selectivity to 1/3, really + * need a true selectivity function. + */ + clauseinfo->selectivity = (Cost) 0.3333333; + } + else + { + clauseinfo->selectivity = + compute_clause_selec(root, (Node *) clause, + NIL); + } + add_join_clause_info_to_rels(root, clauseinfo, relids); + add_vars_to_rels(root, vars, relids); + } } -/* +/* * add-join-clause-info-to-rels-- - * For every relation participating in a join clause, add 'clauseinfo' to - * the appropriate joininfo node(creating a new one and adding it to the - * appropriate rel node if necessary). - * + * For every relation participating in a join clause, add 'clauseinfo' to + * the appropriate joininfo node(creating a new one and adding it to the + * appropriate rel node if necessary). + * * 'clauseinfo' describes the join clause * 'join-relids' is the list of relations participating in the join clause - * + * * Returns nothing. - * + * */ static void -add_join_clause_info_to_rels(Query *root, CInfo *clauseinfo, List *join_relids) +add_join_clause_info_to_rels(Query * root, CInfo * clauseinfo, List * join_relids) { - List *join_relid; - - foreach (join_relid, join_relids) { - JInfo *joininfo; - List *other_rels = NIL; - List *rel; - - foreach (rel, join_relids) - { - if ( lfirsti(rel) != lfirsti(join_relid) ) - other_rels = lappendi (other_rels, lfirsti(rel)); - } - - joininfo = - find_joininfo_node(get_base_rel(root, lfirsti(join_relid)), - other_rels); - joininfo->jinfoclauseinfo = - lcons(copyObject((void*)clauseinfo), joininfo->jinfoclauseinfo); - - } + List *join_relid; + + foreach(join_relid, join_relids) + { + JInfo *joininfo; + List *other_rels = NIL; + List *rel; + + foreach(rel, join_relids) + { + if (lfirsti(rel) != lfirsti(join_relid)) + other_rels = lappendi(other_rels, lfirsti(rel)); + } + + joininfo = + find_joininfo_node(get_base_rel(root, lfirsti(join_relid)), + other_rels); + joininfo->jinfoclauseinfo = + lcons(copyObject((void *) clauseinfo), joininfo->jinfoclauseinfo); + + } } -/* +/* * add-vars-to-rels-- - * For each variable appearing in a clause, - * (1) If a targetlist entry for the variable is not already present in - * the appropriate relation's target list, add one. - * (2) If a targetlist entry is already present, but the var is part of a - * join clause, add the relids of the join relations to the JoinList - * entry of the targetlist entry. - * - * 'vars' is the list of var nodes - * 'join-relids' is the list of relids appearing in the join clause - * (if this is a join clause) - * - * Returns nothing. + * For each variable appearing in a clause, + * (1) If a targetlist entry for the variable is not already present in + * the appropriate relation's target list, add one. + * (2) If a targetlist entry is already present, but the var is part of a + * join clause, add the relids of the join relations to the JoinList + * entry of the targetlist entry. + * + * 'vars' is the list of var nodes + * 'join-relids' is the list of relids appearing in the join clause + * (if this is a join clause) + * + * Returns nothing. */ static void -add_vars_to_rels(Query *root, List *vars, List *join_relids) +add_vars_to_rels(Query * root, List * vars, List * join_relids) { - Var *var; - List *temp = NIL; - Rel *rel = (Rel*)NULL; - TargetEntry *tlistentry; - - foreach (temp, vars) { - var = (Var*)lfirst(temp); - rel = get_base_rel(root, var->varno); - tlistentry = tlistentry_member(var, rel->targetlist); - if(tlistentry==NULL) - /* add a new entry */ - add_tl_element(rel, var); - } + Var *var; + List *temp = NIL; + Rel *rel = (Rel *) NULL; + TargetEntry *tlistentry; + + foreach(temp, vars) + { + var = (Var *) lfirst(temp); + rel = get_base_rel(root, var->varno); + tlistentry = tlistentry_member(var, rel->targetlist); + if (tlistentry == NULL) + /* add a new entry */ + add_tl_element(rel, var); + } } /***************************************************************************** * - * JOININFO + * JOININFO * *****************************************************************************/ -/* +/* * initialize-join-clause-info-- - * Set the MergeSortable or HashJoinable field for every joininfo node - * (within a rel node) and the MergeSortOrder or HashJoinOp field for - * each clauseinfo node(within a joininfo node) for all relations in a - * query. - * - * Returns nothing. + * Set the MergeSortable or HashJoinable field for every joininfo node + * (within a rel node) and the MergeSortOrder or HashJoinOp field for + * each clauseinfo node(within a joininfo node) for all relations in a + * query. + * + * Returns nothing. */ void -initialize_join_clause_info(List *rel_list) +initialize_join_clause_info(List * rel_list) { - List *x, *y, *z; - Rel *rel; - JInfo *joininfo; - CInfo *clauseinfo; - Expr *clause; - - foreach (x, rel_list) { - rel = (Rel*)lfirst(x); - foreach (y, rel->joininfo) { - joininfo = (JInfo*)lfirst(y); - foreach (z, joininfo->jinfoclauseinfo) { - clauseinfo = (CInfo*)lfirst(z); - clause = clauseinfo->clause; - if(join_clause_p((Node*)clause)) { - MergeOrder *sortop = (MergeOrder*)NULL; - Oid hashop = (Oid)NULL; - - if (_enable_mergesort_) - sortop = mergesortop(clause); - if (_enable_hashjoin_) - hashop = hashjoinop(clause); - - if (sortop) { - clauseinfo->mergesortorder = sortop; - joininfo->mergesortable = true; - } - if (hashop) { - clauseinfo->hashjoinoperator = hashop; - joininfo->hashjoinable = true; - } + List *x, + *y, + *z; + Rel *rel; + JInfo *joininfo; + CInfo *clauseinfo; + Expr *clause; + + foreach(x, rel_list) + { + rel = (Rel *) lfirst(x); + foreach(y, rel->joininfo) + { + joininfo = (JInfo *) lfirst(y); + foreach(z, joininfo->jinfoclauseinfo) + { + clauseinfo = (CInfo *) lfirst(z); + clause = clauseinfo->clause; + if (join_clause_p((Node *) clause)) + { + MergeOrder *sortop = (MergeOrder *) NULL; + Oid hashop = (Oid) NULL; + + if (_enable_mergesort_) + sortop = mergesortop(clause); + if (_enable_hashjoin_) + hashop = hashjoinop(clause); + + if (sortop) + { + clauseinfo->mergesortorder = sortop; + joininfo->mergesortable = true; + } + if (hashop) + { + clauseinfo->hashjoinoperator = hashop; + joininfo->hashjoinable = true; + } + } + } } - } } - } } -/* +/* * mergesortop-- - * Returns the mergesort operator of an operator iff 'clause' is - * mergesortable, i.e., both operands are single vars and the operator is - * a mergesortable operator. + * Returns the mergesort operator of an operator iff 'clause' is + * mergesortable, i.e., both operands are single vars and the operator is + * a mergesortable operator. */ static MergeOrder * -mergesortop(Expr *clause) +mergesortop(Expr * clause) { - Oid leftOp, rightOp; - bool sortable; - - sortable = op_mergesortable(((Oper*)clause->oper)->opno, - (get_leftop(clause))->vartype, - (get_rightop(clause))->vartype, - &leftOp, - &rightOp); - - if (sortable) { - MergeOrder *morder = makeNode(MergeOrder); - - morder->join_operator = ((Oper*)clause->oper)->opno; - morder->left_operator = leftOp; - morder->right_operator = rightOp; - morder->left_type = (get_leftop(clause))->vartype; - morder->right_type = (get_rightop(clause))->vartype; - return (morder); - } else - return(NULL); + Oid leftOp, + rightOp; + bool sortable; + + sortable = op_mergesortable(((Oper *) clause->oper)->opno, + (get_leftop(clause))->vartype, + (get_rightop(clause))->vartype, + &leftOp, + &rightOp); + + if (sortable) + { + MergeOrder *morder = makeNode(MergeOrder); + + morder->join_operator = ((Oper *) clause->oper)->opno; + morder->left_operator = leftOp; + morder->right_operator = rightOp; + morder->left_type = (get_leftop(clause))->vartype; + morder->right_type = (get_rightop(clause))->vartype; + return (morder); + } + else + return (NULL); } -/* +/* * hashjoinop-- - * Returns the hashjoin operator of an operator iff 'clause' is - * hashjoinable, i.e., both operands are single vars and the operator is - * a hashjoinable operator. + * Returns the hashjoin operator of an operator iff 'clause' is + * hashjoinable, i.e., both operands are single vars and the operator is + * a hashjoinable operator. */ -static Oid -hashjoinop(Expr *clause) +static Oid +hashjoinop(Expr * clause) { - return(op_hashjoinable(((Oper*)clause->oper)->opno, - (get_leftop(clause))->vartype, - (get_rightop(clause))->vartype)); + return (op_hashjoinable(((Oper *) clause->oper)->opno, + (get_leftop(clause))->vartype, + (get_rightop(clause))->vartype)); } |