diff options
Diffstat (limited to 'src/backend/optimizer')
26 files changed, 852 insertions, 732 deletions
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 4422e03cb40..dd3d6bd5372 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: geqo_eval.c,v 1.57 2001/01/24 19:42:57 momjian Exp $ + * $Id: geqo_eval.c,v 1.58 2001/03/22 03:59:33 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -49,8 +49,8 @@ geqo_eval(Query *root, List *initial_rels, Gene *tour, int num_gene) * allocated inside gimme_tree(). * * Since geqo_eval() will be called many times, we can't afford to let - * all that memory go unreclaimed until end of statement. Note we make - * the temp context a child of TransactionCommandContext, so that + * all that memory go unreclaimed until end of statement. Note we + * make the temp context a child of TransactionCommandContext, so that * it will be freed even if we abort via elog(ERROR). */ mycontext = AllocSetContextCreate(TransactionCommandContext, diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index 2300f8677c1..86b5b334097 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: geqo_main.c,v 1.26 2001/01/24 19:42:57 momjian Exp $ + * $Id: geqo_main.c,v 1.27 2001/03/22 03:59:33 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -36,11 +36,11 @@ /* * Configuration options */ -int Geqo_pool_size; -int Geqo_effort; -int Geqo_generations; +int Geqo_pool_size; +int Geqo_effort; +int Geqo_generations; double Geqo_selection_bias; -int Geqo_random_seed; +int Geqo_random_seed; static int gimme_pool_size(int nr_rel); @@ -101,10 +101,10 @@ geqo(Query *root, int number_of_rels, List *initial_rels) /* seed random number generator */ /* XXX why is this done every time around? */ - if (Geqo_random_seed >= 0) - srandom((unsigned int) Geqo_random_seed); - else - srandom((unsigned int) time(NULL)); + if (Geqo_random_seed >= 0) + srandom((unsigned int) Geqo_random_seed); + else + srandom((unsigned int) time(NULL)); /* allocate genetic pool memory */ pool = alloc_pool(pool_size, number_of_rels); @@ -160,8 +160,8 @@ geqo(Query *root, int number_of_rels, List *initial_rels) { /* SELECTION */ - geqo_selection(momma, daddy, pool, Geqo_selection_bias);/* using linear bias - * function */ + geqo_selection(momma, daddy, pool, Geqo_selection_bias); /* using linear bias + * function */ @@ -293,15 +293,15 @@ gimme_pool_size(int nr_rel) { double size; - if (Geqo_pool_size != 0) - { - if (Geqo_pool_size < MIN_GEQO_POOL_SIZE) - return MIN_GEQO_POOL_SIZE; - else if (Geqo_pool_size > MAX_GEQO_POOL_SIZE) - return MAX_GEQO_POOL_SIZE; - else - return Geqo_pool_size; - } + if (Geqo_pool_size != 0) + { + if (Geqo_pool_size < MIN_GEQO_POOL_SIZE) + return MIN_GEQO_POOL_SIZE; + else if (Geqo_pool_size > MAX_GEQO_POOL_SIZE) + return MAX_GEQO_POOL_SIZE; + else + return Geqo_pool_size; + } size = pow(2.0, nr_rel + 1.0); @@ -323,8 +323,8 @@ gimme_pool_size(int nr_rel) static int gimme_number_generations(int pool_size, int effort) { - if (Geqo_generations <= 0) - return effort * (int) ceil(log((double) pool_size) / log(2.0)); - else - return Geqo_generations; + if (Geqo_generations <= 0) + return effort * (int) ceil(log((double) pool_size) / log(2.0)); + else + return Geqo_generations; } diff --git a/src/backend/optimizer/path/_deadcode/predmig.c b/src/backend/optimizer/path/_deadcode/predmig.c index bb73132240a..1781f43db1d 100644 --- a/src/backend/optimizer/path/_deadcode/predmig.c +++ b/src/backend/optimizer/path/_deadcode/predmig.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/predmig.c,v 1.8 2001/01/24 19:42:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/predmig.c,v 1.9 2001/03/22 03:59:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -485,7 +485,7 @@ xfunc_form_groups(Query *queryInfo, Stream root, Stream bottom) } -/* ------------------- UTILITY FUNCTIONS ------------------------- */ +/* ------------------- UTILITY FUNCTIONS ------------------------- */ /* ** xfunc_free_stream diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 7d44c4dcfa0..1cf73dffff7 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.71 2001/02/03 21:17:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.72 2001/03/22 03:59:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,12 +33,12 @@ int geqo_rels = DEFAULT_GEQO_RELS; static void set_base_rel_pathlists(Query *root); static void set_plain_rel_pathlist(Query *root, RelOptInfo *rel, - RangeTblEntry *rte); + RangeTblEntry *rte); static void set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, - RangeTblEntry *rte, - List *inheritlist); + RangeTblEntry *rte, + List *inheritlist); static RelOptInfo *make_one_rel_by_joins(Query *root, int levels_needed, - List *initial_rels); + List *initial_rels); #ifdef OPTIMIZER_DEBUG static void debug_print_rel(Query *root, RelOptInfo *rel); @@ -94,7 +94,7 @@ set_base_rel_pathlists(Query *root) RangeTblEntry *rte; List *inheritlist; - Assert(length(rel->relids) == 1); /* better be base rel */ + Assert(length(rel->relids) == 1); /* better be base rel */ rti = lfirsti(rel->relids); rte = rt_fetch(rti, root->rtable); @@ -103,24 +103,25 @@ set_base_rel_pathlists(Query *root) /* Subquery --- generate a separate plan for it */ /* - * If there are any restriction clauses that have been attached - * to the subquery relation, consider pushing them down to become - * HAVING quals of the subquery itself. (Not WHERE clauses, since - * they may refer to subquery outputs that are aggregate results. - * But planner.c will transfer them into the subquery's WHERE if - * they do not.) This transformation is useful because it may - * allow us to generate a better plan for the subquery than - * evaluating all the subquery output rows and then filtering - * them. + * If there are any restriction clauses that have been + * attached to the subquery relation, consider pushing them + * down to become HAVING quals of the subquery itself. (Not + * WHERE clauses, since they may refer to subquery outputs + * that are aggregate results. But planner.c will transfer + * them into the subquery's WHERE if they do not.) This + * transformation is useful because it may allow us to + * generate a better plan for the subquery than evaluating all + * the subquery output rows and then filtering them. * - * Currently, we do not push down clauses that contain subselects, - * mainly because I'm not sure it will work correctly (the - * subplan hasn't yet transformed sublinks to subselects). - * Also, if the subquery contains set ops (UNION/INTERSECT/EXCEPT) - * we do not push down any qual clauses, since the planner doesn't - * support quals at the top level of a setop. (With suitable - * analysis we could try to push the quals down into the component - * queries of the setop, but getting it right is not trivial.) + * Currently, we do not push down clauses that contain + * subselects, mainly because I'm not sure it will work + * correctly (the subplan hasn't yet transformed sublinks to + * subselects). Also, if the subquery contains set ops + * (UNION/INTERSECT/EXCEPT) we do not push down any qual + * clauses, since the planner doesn't support quals at the top + * level of a setop. (With suitable analysis we could try to + * push the quals down into the component queries of the + * setop, but getting it right is not trivial.) * Non-pushed-down clauses will get evaluated as qpquals of * the SubqueryScan node. * @@ -136,8 +137,8 @@ set_base_rel_pathlists(Query *root) foreach(lst, rel->baserestrictinfo) { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lst); - Node *clause = (Node *) rinfo->clause; + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lst); + Node *clause = (Node *) rinfo->clause; if (contain_subplans(clause)) { @@ -146,13 +147,14 @@ set_base_rel_pathlists(Query *root) } else { + /* - * We need to replace Vars in the clause (which must - * refer to outputs of the subquery) with copies of - * the subquery's targetlist expressions. Note that - * at this point, any uplevel Vars in the clause - * should have been replaced with Params, so they - * need no work. + * We need to replace Vars in the clause (which + * must refer to outputs of the subquery) with + * copies of the subquery's targetlist + * expressions. Note that at this point, any + * uplevel Vars in the clause should have been + * replaced with Params, so they need no work. */ clause = ResolveNew(clause, rti, 0, rte->subquery->targetList, @@ -160,11 +162,12 @@ set_base_rel_pathlists(Query *root) rte->subquery->havingQual = make_and_qual(rte->subquery->havingQual, clause); + /* * We need not change the subquery's hasAggs or - * hasSublinks flags, since we can't be pushing down - * any aggregates that weren't there before, and we - * don't push down subselects at all. + * hasSublinks flags, since we can't be pushing + * down any aggregates that weren't there before, + * and we don't push down subselects at all. */ } } @@ -215,9 +218,9 @@ set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) /* * Generate paths and add them to the rel's pathlist. * - * Note: add_path() will discard any paths that are dominated by - * another available path, keeping only those paths that are - * superior along at least one dimension of cost or sortedness. + * Note: add_path() will discard any paths that are dominated by another + * available path, keeping only those paths that are superior along at + * least one dimension of cost or sortedness. */ /* Consider sequential scan */ @@ -230,9 +233,9 @@ set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte) create_index_paths(root, rel, indices); /* - * Note: create_or_index_paths depends on create_index_paths to - * have marked OR restriction clauses with relevant indices; this - * is why it doesn't need to be given the list of indices. + * Note: create_or_index_paths depends on create_index_paths to have + * marked OR restriction clauses with relevant indices; this is why it + * doesn't need to be given the list of indices. */ create_or_index_paths(root, rel, rel->baserestrictinfo); @@ -258,8 +261,8 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte, List *il; /* - * XXX for now, can't handle inherited expansion of FOR UPDATE; - * can we do better? + * XXX for now, can't handle inherited expansion of FOR UPDATE; can we + * do better? */ if (intMember(parentRTindex, root->rowMarks)) elog(ERROR, "SELECT FOR UPDATE is not supported for inherit queries"); @@ -271,14 +274,14 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte, rel->width = 0; /* - * Generate access paths for each table in the tree (parent AND children), - * and pick the cheapest path for each table. + * Generate access paths for each table in the tree (parent AND + * children), and pick the cheapest path for each table. */ foreach(il, inheritlist) { - int childRTindex = lfirsti(il); + int childRTindex = lfirsti(il); RangeTblEntry *childrte; - Oid childOID; + Oid childOID; RelOptInfo *childrel; childrte = rt_fetch(childRTindex, root->rtable); @@ -289,16 +292,18 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte, * attach the RelOptInfo to the query's base_rel_list, however. * * NOTE: when childRTindex == parentRTindex, we create a second - * RelOptInfo for the same relation. This RelOptInfo will represent - * the parent table alone, whereas the original RelOptInfo represents - * the union of the inheritance tree members. + * RelOptInfo for the same relation. This RelOptInfo will + * represent the parent table alone, whereas the original + * RelOptInfo represents the union of the inheritance tree + * members. */ childrel = make_base_rel(root, childRTindex); /* - * Copy the parent's targetlist and restriction quals to the child, - * with attribute-number adjustment if needed. We don't bother - * to copy the join quals, since we can't do any joining here. + * Copy the parent's targetlist and restriction quals to the + * child, with attribute-number adjustment if needed. We don't + * bother to copy the join quals, since we can't do any joining + * here. */ childrel->targetlist = (List *) adjust_inherited_attrs((Node *) rel->targetlist, @@ -328,8 +333,8 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte, } /* - * Finally, build Append path and install it as the only access - * path for the parent rel. + * Finally, build Append path and install it as the only access path + * for the parent rel. */ add_path(rel, (Path *) create_append_path(rel, subpaths)); @@ -350,9 +355,9 @@ make_fromexpr_rel(Query *root, FromExpr *from) List *jt; /* - * Count the number of child jointree nodes. This is the depth - * of the dynamic-programming algorithm we must employ to consider - * all ways of joining the child nodes. + * Count the number of child jointree nodes. This is the depth of the + * dynamic-programming algorithm we must employ to consider all ways + * of joining the child nodes. */ levels_needed = length(from->fromlist); @@ -374,6 +379,7 @@ make_fromexpr_rel(Query *root, FromExpr *from) if (levels_needed == 1) { + /* * Single jointree node, so we're done. */ @@ -381,6 +387,7 @@ make_fromexpr_rel(Query *root, FromExpr *from) } else { + /* * Consider the different orders in which we could join the rels, * using either GEQO or regular optimizer. @@ -401,7 +408,7 @@ make_fromexpr_rel(Query *root, FromExpr *from) * independent jointree items in the query. This is > 1. * * 'initial_rels' is a list of RelOptInfo nodes for each independent - * jointree item. These are the components to be joined together. + * jointree item. These are the components to be joined together. * * Returns the final level of join relations, i.e., the relation that is * the result of joining all the original relations together. @@ -423,8 +430,8 @@ make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels) * joinitems[j] is a list of all the j-item rels. Initially we set * joinitems[1] to represent all the single-jointree-item relations. */ - joinitems = (List **) palloc((levels_needed+1) * sizeof(List *)); - MemSet(joinitems, 0, (levels_needed+1) * sizeof(List *)); + joinitems = (List **) palloc((levels_needed + 1) * sizeof(List *)); + MemSet(joinitems, 0, (levels_needed + 1) * sizeof(List *)); joinitems[1] = initial_rels; diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index b404eabccdb..8493067f9a2 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.41 2001/01/24 19:42:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.42 2001/03/22 03:59:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -128,7 +128,8 @@ clauselist_selectivity(Query *root, * behave in the simple way we are expecting.) * * NB: for consistency of results, this fragment of code had better - * match what clause_selectivity() would do in the cases it handles. + * match what clause_selectivity() would do in the cases it + * handles. */ if (varRelid != 0 || NumRelids(clause) == 1) { @@ -148,7 +149,7 @@ clauselist_selectivity(Query *root, get_leftop((Expr *) clause); if (is_pseudo_constant_clause((Node *) other)) { - Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno; + Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno; RegProcedure oprrest = get_oprrest(opno); if (!oprrest) @@ -156,15 +157,16 @@ clauselist_selectivity(Query *root, else s2 = restriction_selectivity(oprrest, opno, getrelid(relidx, - root->rtable), + root->rtable), attno, constval, flag); /* - * If we reach here, we have computed the same result that - * clause_selectivity would, so we can just use s2 if it's - * the wrong oprrest. But if it's the right oprrest, add - * the clause to rqlist for later processing. + * If we reach here, we have computed the same result + * that clause_selectivity would, so we can just use + * s2 if it's the wrong oprrest. But if it's the + * right oprrest, add the clause to rqlist for later + * processing. */ switch (oprrest) { @@ -384,18 +386,20 @@ clause_selectivity(Query *root, if (rte->subquery) { + /* - * XXX not smart about subquery references... - * any way to do better? + * XXX not smart about subquery references... any way to + * do better? */ s1 = 0.5; } else { + /* - * A Var at the top of a clause must be a bool Var. - * This is equivalent to the clause reln.attribute = 't', - * so we compute the selectivity as if that is what we have. + * A Var at the top of a clause must be a bool Var. This + * is equivalent to the clause reln.attribute = 't', so we + * compute the selectivity as if that is what we have. */ s1 = restriction_selectivity(F_EQSEL, BooleanEqualOperator, diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 8e88e46d571..d5b343a90cf 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -41,7 +41,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.68 2001/02/16 00:03:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.69 2001/03/22 03:59:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -67,11 +67,11 @@ #define LOG6(x) (log(x) / 1.79175946922805) -double effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE; -double random_page_cost = DEFAULT_RANDOM_PAGE_COST; -double cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST; -double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST; -double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST; +double effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE; +double random_page_cost = DEFAULT_RANDOM_PAGE_COST; +double cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST; +double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST; +double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST; Cost disable_cost = 100000000.0; @@ -117,14 +117,14 @@ cost_seqscan(Path *path, RelOptInfo *baserel) /* * disk costs * - * The cost of reading a page sequentially is 1.0, by definition. - * Note that the Unix kernel will typically do some amount of - * read-ahead optimization, so that this cost is less than the - * true cost of reading a page from disk. We ignore that issue - * here, but must take it into account when estimating the cost of - * non-sequential accesses! + * The cost of reading a page sequentially is 1.0, by definition. Note + * that the Unix kernel will typically do some amount of read-ahead + * optimization, so that this cost is less than the true cost of + * reading a page from disk. We ignore that issue here, but must take + * it into account when estimating the cost of non-sequential + * accesses! */ - run_cost += baserel->pages; /* sequential fetches with cost 1.0 */ + run_cost += baserel->pages; /* sequential fetches with cost 1.0 */ /* CPU costs */ cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost; @@ -600,12 +600,12 @@ cost_hashjoin(Path *path, /* * The number of tuple comparisons needed is the number of outer * tuples times the typical hash bucket size. nodeHash.c tries for - * average bucket loading of NTUP_PER_BUCKET, but that goal will - * be reached only if data values are uniformly distributed among - * the buckets. To be conservative, we scale up the target bucket - * size by the number of inner rows times inner dispersion, giving - * an estimate of the typical number of duplicates of each value. - * We then charge one cpu_operator_cost per tuple comparison. + * average bucket loading of NTUP_PER_BUCKET, but that goal will be + * reached only if data values are uniformly distributed among the + * buckets. To be conservative, we scale up the target bucket size by + * the number of inner rows times inner dispersion, giving an estimate + * of the typical number of duplicates of each value. We then charge + * one cpu_operator_cost per tuple comparison. */ run_cost += cpu_operator_cost * outer_path->parent->rows * NTUP_PER_BUCKET * ceil(inner_path->parent->rows * innerdispersion); @@ -672,7 +672,7 @@ cost_qual_eval(List *quals) foreach(l, quals) { - Node *qual = (Node *) lfirst(l); + Node *qual = (Node *) lfirst(l); /* * RestrictInfo nodes contain an eval_cost field reserved for this diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index ed5a53db0b9..064a2fafa50 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.102 2001/02/16 03:16:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.103 2001/03/22 03:59:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -183,8 +183,8 @@ create_index_paths(Query *root, restrictinfo_list); /* - * 3. Compute pathkeys describing index's ordering, if any, - * then see how many of them are actually useful for this query. + * 3. Compute pathkeys describing index's ordering, if any, then + * see how many of them are actually useful for this query. */ index_pathkeys = build_index_pathkeys(root, rel, index, ForwardScanDirection); @@ -207,8 +207,9 @@ create_index_paths(Query *root, NoMovementScanDirection)); /* - * 5. If the index is ordered, a backwards scan might be interesting. - * Currently this is only possible for a DESC query result ordering. + * 5. If the index is ordered, a backwards scan might be + * interesting. Currently this is only possible for a DESC query + * result ordering. */ if (index_is_ordered) { @@ -422,10 +423,11 @@ extract_or_indexqual_conditions(RelOptInfo *rel, if (and_clause((Node *) orsubclause)) { + /* - * Extract relevant sub-subclauses in indexkey order. This is just - * like group_clauses_by_indexkey() except that the input and output - * are lists of bare clauses, not of RestrictInfo nodes. + * Extract relevant sub-subclauses in indexkey order. This is + * just like group_clauses_by_indexkey() except that the input and + * output are lists of bare clauses, not of RestrictInfo nodes. */ int *indexkeys = index->indexkeys; Oid *classes = index->classlist; @@ -446,8 +448,8 @@ extract_or_indexqual_conditions(RelOptInfo *rel, } /* - * If no clauses match this key, we're done; we don't want to look - * at keys to its right. + * If no clauses match this key, we're done; we don't want to + * look at keys to its right. */ if (clausegroup == NIL) break; @@ -748,8 +750,8 @@ match_clause_to_indexkey(RelOptInfo *rel, /* * Check for an indexqual that could be handled by a nestloop * join. We need the index key to be compared against an - * expression that uses none of the indexed relation's vars - * and contains no non-cachable functions. + * expression that uses none of the indexed relation's vars and + * contains no non-cachable functions. */ if (match_index_to_operand(indexkey, leftop, rel, index)) { @@ -793,7 +795,7 @@ match_clause_to_indexkey(RelOptInfo *rel, * recognizing binary-compatible datatypes. For example, if we have * an expression like "oid = 123", the operator will be oideqint4, * which we need to replace with oideq in order to recognize it as - * matching an oid_ops index on the oid field. A variant case is where + * matching an oid_ops index on the oid field. A variant case is where * the expression is like "oid::int4 = 123", where the given operator * will be int4eq and again we need to intuit that we want to use oideq. * @@ -832,13 +834,13 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, /* * Maybe the index uses a binary-compatible operator set. * - * Get the nominal input types of the given operator and the actual - * type (before binary-compatible relabeling) of the index key. + * Get the nominal input types of the given operator and the actual type + * (before binary-compatible relabeling) of the index key. */ oldoptup = SearchSysCache(OPEROID, ObjectIdGetDatum(expr_op), 0, 0, 0); - if (! HeapTupleIsValid(oldoptup)) + if (!HeapTupleIsValid(oldoptup)) return InvalidOid; /* probably can't happen */ oldopform = (Form_pg_operator) GETSTRUCT(oldoptup); opname = pstrdup(NameStr(oldopform->oprname)); @@ -848,7 +850,7 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, if (indexkey_on_left) { - Node *leftop = (Node *) get_leftop(clause); + Node *leftop = (Node *) get_leftop(clause); if (leftop && IsA(leftop, RelabelType)) leftop = ((RelabelType *) leftop)->arg; @@ -856,7 +858,7 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, } else { - Node *rightop = (Node *) get_rightop(clause); + Node *rightop = (Node *) get_rightop(clause); if (rightop && IsA(rightop, RelabelType)) rightop = ((RelabelType *) rightop)->arg; @@ -874,9 +876,10 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, return InvalidOid; /* - * OK, look for operator of the same name with the indexkey's data type. - * (In theory this might find a non-semantically-comparable operator, - * but in practice that seems pretty unlikely for binary-compatible types.) + * OK, look for operator of the same name with the indexkey's data + * type. (In theory this might find a non-semantically-comparable + * operator, but in practice that seems pretty unlikely for + * binary-compatible types.) */ new_op = compatible_oper_opid(opname, indexkeytype, indexkeytype, true); @@ -886,8 +889,8 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, { /* - * OK, we found a binary-compatible operator of the same - * name; now does it match the index? + * OK, we found a binary-compatible operator of the same name; + * now does it match the index? */ if (indexkey_on_left) commuted_op = new_op; @@ -1491,8 +1494,9 @@ match_index_to_operand(int indexkey, RelOptInfo *rel, IndexOptInfo *index) { + /* - * Ignore any RelabelType node above the indexkey. This is needed to + * Ignore any RelabelType node above the indexkey. This is needed to * be able to apply indexscanning in binary-compatible-operator cases. * Note: we can assume there is at most one RelabelType node; * eval_const_expressions() will have simplified if more than one. @@ -1670,7 +1674,7 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam, patt = DatumGetCString(DirectFunctionCall1(textout, constvalue)); isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like, - &prefix, &rest) != Pattern_Prefix_None; + &prefix, &rest) != Pattern_Prefix_None; if (prefix) pfree(prefix); pfree(patt); @@ -1687,7 +1691,7 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam, patt = DatumGetCString(DirectFunctionCall1(textout, constvalue)); isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, - &prefix, &rest) != Pattern_Prefix_None; + &prefix, &rest) != Pattern_Prefix_None; if (prefix) pfree(prefix); pfree(patt); @@ -1704,7 +1708,7 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam, patt = DatumGetCString(DirectFunctionCall1(textout, constvalue)); isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex, - &prefix, &rest) != Pattern_Prefix_None; + &prefix, &rest) != Pattern_Prefix_None; if (prefix) pfree(prefix); pfree(patt); @@ -1721,7 +1725,7 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam, patt = DatumGetCString(DirectFunctionCall1(textout, constvalue)); isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, - &prefix, &rest) != Pattern_Prefix_None; + &prefix, &rest) != Pattern_Prefix_None; if (prefix) pfree(prefix); pfree(patt); @@ -1983,8 +1987,8 @@ prefix_quals(Var *leftop, Oid expr_op, result = makeList1(expr); /* - * If we can create a string larger than the prefix, we can say - * "x < greaterstr". + * If we can create a string larger than the prefix, we can say "x < + * greaterstr". */ greaterstr = make_greater_string(prefix, datatype); if (greaterstr) @@ -2025,6 +2029,7 @@ find_operator(const char *opname, Oid datatype) static Datum string_to_datum(const char *str, Oid datatype) { + /* * We cheat a little by assuming that textin() will do for bpchar and * varchar constants too... diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index cfbfb56c902..bfd246388b4 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.61 2001/01/24 19:42:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.62 2001/03/22 03:59:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -25,32 +25,32 @@ #include "utils/lsyscache.h" static void sort_inner_and_outer(Query *root, RelOptInfo *joinrel, - RelOptInfo *outerrel, RelOptInfo *innerrel, - List *restrictlist, List *mergeclause_list, - JoinType jointype); + RelOptInfo *outerrel, RelOptInfo *innerrel, + List *restrictlist, List *mergeclause_list, + JoinType jointype); static void match_unsorted_outer(Query *root, RelOptInfo *joinrel, - RelOptInfo *outerrel, RelOptInfo *innerrel, - List *restrictlist, List *mergeclause_list, - JoinType jointype); + RelOptInfo *outerrel, RelOptInfo *innerrel, + List *restrictlist, List *mergeclause_list, + JoinType jointype); #ifdef NOT_USED static void match_unsorted_inner(Query *root, RelOptInfo *joinrel, - RelOptInfo *outerrel, RelOptInfo *innerrel, - List *restrictlist, List *mergeclause_list, - JoinType jointype); + RelOptInfo *outerrel, RelOptInfo *innerrel, + List *restrictlist, List *mergeclause_list, + JoinType jointype); #endif static void hash_inner_and_outer(Query *root, RelOptInfo *joinrel, - RelOptInfo *outerrel, RelOptInfo *innerrel, - List *restrictlist, JoinType jointype); + RelOptInfo *outerrel, RelOptInfo *innerrel, + List *restrictlist, JoinType jointype); static Path *best_innerjoin(List *join_paths, List *outer_relid, - JoinType jointype); + JoinType jointype); static Selectivity estimate_dispersion(Query *root, Var *var); static List *select_mergejoin_clauses(RelOptInfo *joinrel, - RelOptInfo *outerrel, - RelOptInfo *innerrel, - List *restrictlist, - JoinType jointype); + RelOptInfo *outerrel, + RelOptInfo *innerrel, + List *restrictlist, + JoinType jointype); /* @@ -160,26 +160,27 @@ sort_inner_and_outer(Query *root, * generate a differently-sorted result path at essentially the same * cost. We have no basis for choosing one over another at this level * of joining, but some sort orders may be more useful than others for - * higher-level mergejoins, so it's worth considering multiple orderings. + * higher-level mergejoins, so it's worth considering multiple + * orderings. * * Actually, it's not quite true that every mergeclause ordering will * generate a different path order, because some of the clauses may be - * redundant. Therefore, what we do is convert the mergeclause list to - * a list of canonical pathkeys, and then consider different orderings - * of the pathkeys. + * redundant. Therefore, what we do is convert the mergeclause list + * to a list of canonical pathkeys, and then consider different + * orderings of the pathkeys. * - * Generating a path for *every* permutation of the pathkeys doesn't - * seem like a winning strategy; the cost in planning time is too high. - * For now, we generate one path for each pathkey, listing that pathkey - * first and the rest in random order. This should allow at - * least a one-clause mergejoin without re-sorting against any other - * possible mergejoin partner path. But if we've not guessed the - * right ordering of secondary keys, we may end up evaluating - * clauses as qpquals when they could have been done as mergeclauses. - * We need to figure out a better way. (Two possible approaches: look - * at all the relevant index relations to suggest plausible sort - * orders, or make just one output path and somehow mark it as having - * a sort-order that can be rearranged freely.) + * Generating a path for *every* permutation of the pathkeys doesn't seem + * like a winning strategy; the cost in planning time is too high. For + * now, we generate one path for each pathkey, listing that pathkey + * first and the rest in random order. This should allow at least a + * one-clause mergejoin without re-sorting against any other possible + * mergejoin partner path. But if we've not guessed the right + * ordering of secondary keys, we may end up evaluating clauses as + * qpquals when they could have been done as mergeclauses. We need to + * figure out a better way. (Two possible approaches: look at all the + * relevant index relations to suggest plausible sort orders, or make + * just one output path and somehow mark it as having a sort-order + * that can be rearranged freely.) */ all_pathkeys = make_pathkeys_for_mergeclauses(root, mergeclause_list, @@ -200,16 +201,17 @@ sort_inner_and_outer(Query *root, lremove(front_pathkey, listCopy(all_pathkeys))); else - cur_pathkeys = all_pathkeys; /* no work at first one... */ + cur_pathkeys = all_pathkeys; /* no work at first one... */ /* * Select mergeclause(s) that match this sort ordering. If we had - * redundant merge clauses then we will get a subset of the original - * clause list. There had better be some match, however... + * redundant merge clauses then we will get a subset of the + * original clause list. There had better be some match, + * however... */ cur_mergeclauses = find_mergeclauses_for_pathkeys(root, cur_pathkeys, - mergeclause_list); + mergeclause_list); Assert(cur_mergeclauses != NIL); /* @@ -334,10 +336,12 @@ match_unsorted_outer(Query *root, if (nestjoinOK) { + /* - * Always consider a nestloop join with this outer and cheapest- - * total-cost inner. Consider nestloops using the cheapest- - * startup-cost inner as well, and the best innerjoin indexpath. + * Always consider a nestloop join with this outer and + * cheapest- total-cost inner. Consider nestloops using the + * cheapest- startup-cost inner as well, and the best + * innerjoin indexpath. */ add_path(joinrel, (Path *) create_nestloop_path(joinrel, @@ -352,7 +356,7 @@ match_unsorted_outer(Query *root, create_nestloop_path(joinrel, jointype, outerpath, - innerrel->cheapest_startup_path, + innerrel->cheapest_startup_path, restrictlist, merge_pathkeys)); if (bestinnerjoin != NULL) @@ -382,8 +386,8 @@ match_unsorted_outer(Query *root, /* * Generate a mergejoin on the basis of sorting the cheapest * inner. Since a sort will be needed, only cheapest total cost - * matters. (But create_mergejoin_path will do the right thing - * if innerrel->cheapest_total_path is already correctly sorted.) + * matters. (But create_mergejoin_path will do the right thing if + * innerrel->cheapest_total_path is already correctly sorted.) */ add_path(joinrel, (Path *) create_mergejoin_path(joinrel, @@ -400,13 +404,14 @@ match_unsorted_outer(Query *root, * Look for presorted inner paths that satisfy the innersortkey * list or any truncation thereof. Here, we consider both cheap * startup cost and cheap total cost. Ignore - * innerrel->cheapest_total_path, since we already made a path with it. + * innerrel->cheapest_total_path, since we already made a path + * with it. */ num_sortkeys = length(innersortkeys); if (num_sortkeys > 1) - trialsortkeys = listCopy(innersortkeys); /* need modifiable copy */ + trialsortkeys = listCopy(innersortkeys); /* need modifiable copy */ else - trialsortkeys = innersortkeys; /* won't really truncate */ + trialsortkeys = innersortkeys; /* won't really truncate */ cheapest_startup_inner = NULL; cheapest_total_inner = NULL; @@ -417,8 +422,8 @@ match_unsorted_outer(Query *root, /* * Look for an inner path ordered well enough for the first - * 'sortkeycnt' innersortkeys. NB: trialsortkeys list - * is modified destructively, which is why we made a copy... + * 'sortkeycnt' innersortkeys. NB: trialsortkeys list is + * modified destructively, which is why we made a copy... */ trialsortkeys = ltruncate(sortkeycnt, trialsortkeys); innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist, @@ -478,8 +483,8 @@ match_unsorted_outer(Query *root, { newclauses = find_mergeclauses_for_pathkeys(root, - trialsortkeys, - mergeclauses); + trialsortkeys, + mergeclauses); Assert(newclauses != NIL); } else @@ -601,7 +606,7 @@ match_unsorted_inner(Query *root, if (startupouterpath != NULL && startupouterpath != totalouterpath) { merge_pathkeys = build_join_pathkeys(root, joinrel, - startupouterpath->pathkeys); + startupouterpath->pathkeys); add_path(joinrel, (Path *) create_mergejoin_path(joinrel, jointype, @@ -696,8 +701,8 @@ hash_inner_and_outer(Query *root, * estimate dispersion of inner var for costing purposes. * * Since we tend to visit the same clauses over and over when - * planning a large query, we cache the dispersion estimates in the - * RestrictInfo node to avoid repeated lookups of statistics. + * planning a large query, we cache the dispersion estimates in + * the RestrictInfo node to avoid repeated lookups of statistics. */ if (intMember(left->varno, outerrelids) && intMember(right->varno, innerrelids)) @@ -793,13 +798,13 @@ best_innerjoin(List *join_paths, Relids outer_relids, JoinType jointype) foreach(join_path, join_paths) { - IndexPath *path = (IndexPath *) lfirst(join_path); + IndexPath *path = (IndexPath *) lfirst(join_path); Assert(IsA(path, IndexPath)); /* - * If processing an outer join, only use explicit join clauses in the - * inner indexscan. For inner joins we need not be so picky. + * If processing an outer join, only use explicit join clauses in + * the inner indexscan. For inner joins we need not be so picky. */ if (isouterjoin && !path->alljoinquals) continue; @@ -879,15 +884,15 @@ select_mergejoin_clauses(RelOptInfo *joinrel, *right; /* - * If processing an outer join, only use its own join clauses in the - * merge. For inner joins we need not be so picky. + * If processing an outer join, only use its own join clauses in + * the merge. For inner joins we need not be so picky. * * Furthermore, if it is a right/full join then *all* the explicit - * join clauses must be mergejoinable, else the executor will fail. - * If we are asked for a right join then just return NIL to indicate - * no mergejoin is possible (we can handle it as a left join instead). - * If we are asked for a full join then emit an error, because there - * is no fallback. + * join clauses must be mergejoinable, else the executor will + * fail. If we are asked for a right join then just return NIL to + * indicate no mergejoin is possible (we can handle it as a left + * join instead). If we are asked for a full join then emit an + * error, because there is no fallback. */ if (isouterjoin) { @@ -897,7 +902,7 @@ select_mergejoin_clauses(RelOptInfo *joinrel, { case JOIN_RIGHT: if (restrictinfo->mergejoinoperator == InvalidOid) - return NIL; /* not mergejoinable */ + return NIL; /* not mergejoinable */ break; case JOIN_FULL: if (restrictinfo->mergejoinoperator == InvalidOid) diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 2492f17ea9b..929a977112d 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.51 2001/02/16 00:03:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.52 2001/03/22 03:59:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ static RelOptInfo *make_join_rel(Query *root, RelOptInfo *rel1, - RelOptInfo *rel2, JoinType jointype); + RelOptInfo *rel2, JoinType jointype); /* @@ -44,18 +44,19 @@ make_rels_by_joins(Query *root, int level, List **joinrels) /* * First, consider left-sided and right-sided plans, in which rels of - * exactly level-1 member relations are joined against initial relations. - * We prefer to join using join clauses, but if we find a rel of level-1 - * members that has no join clauses, we will generate Cartesian-product - * joins against all initial rels not already contained in it. + * exactly level-1 member relations are joined against initial + * relations. We prefer to join using join clauses, but if we find a + * rel of level-1 members that has no join clauses, we will generate + * Cartesian-product joins against all initial rels not already + * contained in it. * - * In the first pass (level == 2), we try to join each initial rel to each - * initial rel that appears later in joinrels[1]. (The mirror-image - * joins are handled automatically by make_join_rel.) In later - * passes, we try to join rels of size level-1 from joinrels[level-1] - * to each initial rel in joinrels[1]. + * In the first pass (level == 2), we try to join each initial rel to + * each initial rel that appears later in joinrels[1]. (The + * mirror-image joins are handled automatically by make_join_rel.) In + * later passes, we try to join rels of size level-1 from + * joinrels[level-1] to each initial rel in joinrels[1]. */ - foreach(r, joinrels[level-1]) + foreach(r, joinrels[level - 1]) { RelOptInfo *old_rel = (RelOptInfo *) lfirst(r); List *other_rels; @@ -73,9 +74,9 @@ make_rels_by_joins(Query *root, int level, List **joinrels) * Note that if all available join clauses for this rel * require more than one other rel, we will fail to make any * joins against it here. That's OK; it'll be considered by - * "bushy plan" join code in a higher-level pass where we - * have those other rels collected into a join rel. See also - * the last-ditch case below. + * "bushy plan" join code in a higher-level pass where we have + * those other rels collected into a join rel. See also the + * last-ditch case below. */ new_rels = make_rels_by_clause_joins(root, old_rel, @@ -94,16 +95,16 @@ make_rels_by_joins(Query *root, int level, List **joinrels) } /* - * At levels above 2 we will generate the same joined relation - * in multiple ways --- for example (a join b) join c is the same + * At levels above 2 we will generate the same joined relation in + * multiple ways --- for example (a join b) join c is the same * RelOptInfo as (b join c) join a, though the second case will - * add a different set of Paths to it. To avoid making extra work - * for subsequent passes, do not enter the same RelOptInfo into our - * output list multiple times. + * add a different set of Paths to it. To avoid making extra work + * for subsequent passes, do not enter the same RelOptInfo into + * our output list multiple times. */ foreach(nr, new_rels) { - RelOptInfo *jrel = (RelOptInfo *) lfirst(nr); + RelOptInfo *jrel = (RelOptInfo *) lfirst(nr); if (!ptrMember(jrel, result_rels)) result_rels = lcons(jrel, result_rels); @@ -111,20 +112,21 @@ make_rels_by_joins(Query *root, int level, List **joinrels) } /* - * Now, consider "bushy plans" in which relations of k initial rels are - * joined to relations of level-k initial rels, for 2 <= k <= level-2. + * Now, consider "bushy plans" in which relations of k initial rels + * are joined to relations of level-k initial rels, for 2 <= k <= + * level-2. * * We only consider bushy-plan joins for pairs of rels where there is a * suitable join clause, in order to avoid unreasonable growth of * planning time. */ - for (k = 2; ; k++) + for (k = 2;; k++) { int other_level = level - k; /* - * Since make_join_rel(x, y) handles both x,y and y,x cases, - * we only need to go as far as the halfway point. + * Since make_join_rel(x, y) handles both x,y and y,x cases, we + * only need to go as far as the halfway point. */ if (k > other_level) break; @@ -139,7 +141,7 @@ make_rels_by_joins(Query *root, int level, List **joinrels) continue; /* we ignore clauseless joins here */ if (k == other_level) - other_rels = lnext(r); /* only consider remaining rels */ + other_rels = lnext(r); /* only consider remaining rels */ else other_rels = joinrels[other_level]; @@ -153,8 +155,8 @@ make_rels_by_joins(Query *root, int level, List **joinrels) /* * OK, we can build a rel of the right level from this - * pair of rels. Do so if there is at least one usable - * join clause. + * pair of rels. Do so if there is at least one + * usable join clause. */ foreach(i, old_rel->joininfo) { @@ -170,7 +172,8 @@ make_rels_by_joins(Query *root, int level, List **joinrels) /* Avoid making duplicate entries ... */ if (!ptrMember(jrel, result_rels)) result_rels = lcons(jrel, result_rels); - break; /* need not consider more joininfos */ + break; /* need not consider more + * joininfos */ } } } @@ -180,31 +183,34 @@ make_rels_by_joins(Query *root, int level, List **joinrels) /* * Last-ditch effort: if we failed to find any usable joins so far, - * force a set of cartesian-product joins to be generated. This + * force a set of cartesian-product joins to be generated. This * handles the special case where all the available rels have join - * clauses but we cannot use any of the joins yet. An example is + * clauses but we cannot use any of the joins yet. An example is * * SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0; * - * The join clause will be usable at level 3, but at level 2 we have - * no choice but to make cartesian joins. We consider only left-sided + * The join clause will be usable at level 3, but at level 2 we have no + * choice but to make cartesian joins. We consider only left-sided * and right-sided cartesian joins in this case (no bushy). */ if (result_rels == NIL) { - /* This loop is just like the first one, except we always call + + /* + * This loop is just like the first one, except we always call * make_rels_by_clauseless_joins(). */ - foreach(r, joinrels[level-1]) + foreach(r, joinrels[level - 1]) { RelOptInfo *old_rel = (RelOptInfo *) lfirst(r); List *other_rels; if (level == 2) - other_rels = lnext(r); /* only consider remaining initial - * rels */ + other_rels = lnext(r); /* only consider remaining initial + * rels */ else - other_rels = joinrels[1]; /* consider all initial rels */ + other_rels = joinrels[1]; /* consider all initial + * rels */ new_rels = make_rels_by_clauseless_joins(root, old_rel, @@ -212,7 +218,7 @@ make_rels_by_joins(Query *root, int level, List **joinrels) foreach(nr, new_rels) { - RelOptInfo *jrel = (RelOptInfo *) lfirst(nr); + RelOptInfo *jrel = (RelOptInfo *) lfirst(nr); if (!ptrMember(jrel, result_rels)) result_rels = lcons(jrel, result_rels); @@ -266,6 +272,7 @@ make_rels_by_clause_joins(Query *root, RelOptInfo *jrel; jrel = make_join_rel(root, old_rel, other_rel, JOIN_INNER); + /* * Avoid entering same joinrel into our output list more * than once. (make_rels_by_joins doesn't really care, @@ -310,9 +317,10 @@ make_rels_by_clauseless_joins(Query *root, RelOptInfo *jrel; jrel = make_join_rel(root, old_rel, other_rel, JOIN_INNER); + /* - * As long as given other_rels are distinct, don't need - * to test to see if jrel is already part of output list. + * As long as given other_rels are distinct, don't need to + * test to see if jrel is already part of output list. */ result = lcons(jrel, result); } @@ -325,7 +333,7 @@ make_rels_by_clauseless_joins(Query *root, /* * make_jointree_rel * Find or build a RelOptInfojoin rel representing a specific - * jointree item. For JoinExprs, we only consider the construction + * jointree item. For JoinExprs, we only consider the construction * path that corresponds exactly to what the user wrote. */ RelOptInfo * diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index e96a96f6deb..f93a027cd53 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.30 2001/01/24 19:42:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.31 2001/03/22 03:59:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ static PathKeyItem *makePathKeyItem(Node *key, Oid sortop); static List *make_canonical_pathkey(Query *root, PathKeyItem *item); static Var *find_indexkey_var(Query *root, RelOptInfo *rel, - AttrNumber varattno); + AttrNumber varattno); /* @@ -89,10 +89,10 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo) * into our new set. When done, we add the new set to the front of * equi_key_list. * - * It may well be that the two items we're given are already known to - * be equijoin-equivalent, in which case we don't need to change our - * data structure. If we find both of them in the same equivalence - * set to start with, we can quit immediately. + * It may well be that the two items we're given are already known to be + * equijoin-equivalent, in which case we don't need to change our data + * structure. If we find both of them in the same equivalence set to + * start with, we can quit immediately. * * This is a standard UNION-FIND problem, for which there exist better * data structures than simple lists. If this code ever proves to be @@ -109,7 +109,11 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo) if (item1here || item2here) { - /* If find both in same equivalence set, no need to do any more */ + + /* + * If find both in same equivalence set, no need to do any + * more + */ if (item1here && item2here) { /* Better not have seen only one in an earlier set... */ @@ -126,7 +130,8 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo) /* * Remove old set from equi_key_list. NOTE this does not - * change lnext(cursetlink), so the foreach loop doesn't break. + * change lnext(cursetlink), so the foreach loop doesn't + * break. */ root->equi_key_list = lremove(curset, root->equi_key_list); freeList(curset); /* might as well recycle old cons cells */ @@ -171,8 +176,8 @@ generate_implied_equalities(Query *root) continue; /* - * Match each item in the set with all that appear after it - * (it's sufficient to generate A=B, need not process B=A too). + * Match each item in the set with all that appear after it (it's + * sufficient to generate A=B, need not process B=A too). */ foreach(ptr1, curset) { @@ -246,11 +251,12 @@ canonicalize_pathkeys(Query *root, List *pathkeys) Assert(pathkey != NIL); item = (PathKeyItem *) lfirst(pathkey); cpathkey = make_canonical_pathkey(root, item); + /* - * Eliminate redundant ordering requests --- ORDER BY A,A - * is the same as ORDER BY A. We want to check this only - * after we have canonicalized the keys, so that equivalent-key - * knowledge is used when deciding if an item is redundant. + * Eliminate redundant ordering requests --- ORDER BY A,A is the + * same as ORDER BY A. We want to check this only after we have + * canonicalized the keys, so that equivalent-key knowledge is + * used when deciding if an item is redundant. */ if (!ptrMember(cpathkey, new_pathkeys)) new_pathkeys = lappend(new_pathkeys, cpathkey); @@ -285,8 +291,8 @@ compare_pathkeys(List *keys1, List *keys2) List *subkey2 = lfirst(key2); /* - * XXX would like to check that we've been given canonicalized input, - * but query root not accessible here... + * XXX would like to check that we've been given canonicalized + * input, but query root not accessible here... */ #ifdef NOT_USED Assert(ptrMember(subkey1, root->equi_key_list)); @@ -295,7 +301,7 @@ compare_pathkeys(List *keys1, List *keys2) /* * We will never have two subkeys where one is a subset of the - * other, because of the canonicalization process. Either they + * other, because of the canonicalization process. Either they * are equal or they ain't. Furthermore, we only need pointer * comparison to detect equality. */ @@ -555,9 +561,10 @@ build_index_pathkeys(Query *root, /* OK, make a sublist for this sort key */ item = makePathKeyItem((Node *) relvar, sortop); cpathkey = make_canonical_pathkey(root, item); + /* - * Eliminate redundant ordering info; could happen if query - * is such that index keys are equijoined... + * Eliminate redundant ordering info; could happen if query is + * such that index keys are equijoined... */ if (!ptrMember(cpathkey, retval)) retval = lappend(retval, cpathkey); @@ -693,7 +700,7 @@ make_pathkeys_for_sortclauses(List *sortclauses, * * RestrictInfo contains fields in which we may cache the result * of looking up the canonical pathkeys for the left and right sides - * of the mergeclause. (Note that in normal cases they will be the + * of the mergeclause. (Note that in normal cases they will be the * same, but not if the mergeclause appears above an OUTER JOIN.) * This is a worthwhile savings because these routines will be invoked * many times when dealing with a many-relation query. @@ -756,8 +763,8 @@ find_mergeclauses_for_pathkeys(Query *root, /* * We can match a pathkey against either left or right side of any * mergejoin clause we haven't used yet. For the moment we use a - * dumb "greedy" algorithm with no backtracking. Is it worth being - * any smarter to make a longer list of usable mergeclauses? + * dumb "greedy" algorithm with no backtracking. Is it worth + * being any smarter to make a longer list of usable mergeclauses? * Probably not. */ foreach(j, restrictinfos) @@ -765,9 +772,10 @@ find_mergeclauses_for_pathkeys(Query *root, RestrictInfo *restrictinfo = lfirst(j); cache_mergeclause_pathkeys(root, restrictinfo); + /* - * We can compare canonical pathkey sublists by simple - * pointer equality; see compare_pathkeys. + * We can compare canonical pathkey sublists by simple pointer + * equality; see compare_pathkeys. */ if ((pathkey == restrictinfo->left_pathkey || pathkey == restrictinfo->right_pathkey) && @@ -830,7 +838,7 @@ make_pathkeys_for_mergeclauses(Query *root, cache_mergeclause_pathkeys(root, restrictinfo); key = (Node *) get_leftop(restrictinfo->clause); - if (IsA(key, Var) && intMember(((Var *) key)->varno, rel->relids)) + if (IsA(key, Var) &&intMember(((Var *) key)->varno, rel->relids)) { /* Rel is left side of mergeclause */ pathkey = restrictinfo->left_pathkey; @@ -838,7 +846,7 @@ make_pathkeys_for_mergeclauses(Query *root, else { key = (Node *) get_rightop(restrictinfo->clause); - if (IsA(key, Var) && intMember(((Var *) key)->varno, rel->relids)) + if (IsA(key, Var) &&intMember(((Var *) key)->varno, rel->relids)) { /* Rel is right side of mergeclause */ pathkey = restrictinfo->right_pathkey; @@ -851,13 +859,14 @@ make_pathkeys_for_mergeclauses(Query *root, } /* - * When we are given multiple merge clauses, it's possible that some - * clauses refer to the same vars as earlier clauses. There's no - * reason for us to specify sort keys like (A,B,A) when (A,B) will - * do --- and adding redundant sort keys makes add_path think that - * this sort order is different from ones that are really the same, - * so don't do it. Since we now have a canonicalized pathkey, - * a simple ptrMember test is sufficient to detect redundant keys. + * When we are given multiple merge clauses, it's possible that + * some clauses refer to the same vars as earlier clauses. + * There's no reason for us to specify sort keys like (A,B,A) when + * (A,B) will do --- and adding redundant sort keys makes add_path + * think that this sort order is different from ones that are + * really the same, so don't do it. Since we now have a + * canonicalized pathkey, a simple ptrMember test is sufficient to + * detect redundant keys. */ if (!ptrMember(pathkey, pathkeys)) pathkeys = lappend(pathkeys, pathkey); @@ -911,6 +920,7 @@ pathkeys_useful_for_merging(Query *root, RelOptInfo *rel, List *pathkeys) if (restrictinfo->mergejoinoperator == InvalidOid) continue; cache_mergeclause_pathkeys(root, restrictinfo); + /* * We can compare canonical pathkey sublists by simple * pointer equality; see compare_pathkeys. @@ -984,7 +994,9 @@ truncate_useless_pathkeys(Query *root, nuseful2 = pathkeys_useful_for_ordering(root, pathkeys); if (nuseful2 > nuseful) nuseful = nuseful2; - /* Note: not safe to modify input list destructively, but we can avoid + + /* + * Note: not safe to modify input list destructively, but we can avoid * copying the list if we're not actually going to change it */ if (nuseful == length(pathkeys)) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 738b696306a..8c3b00289d3 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.103 2001/01/24 19:42:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.104 2001/03/22 03:59:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -42,19 +42,19 @@ static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path, static TidScan *create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses); static SubqueryScan *create_subqueryscan_plan(Path *best_path, - List *tlist, List *scan_clauses); + List *tlist, List *scan_clauses); static NestLoop *create_nestloop_plan(NestPath *best_path, List *tlist, - List *joinclauses, List *otherclauses, - Plan *outer_plan, List *outer_tlist, - Plan *inner_plan, List *inner_tlist); + List *joinclauses, List *otherclauses, + Plan *outer_plan, List *outer_tlist, + Plan *inner_plan, List *inner_tlist); static MergeJoin *create_mergejoin_plan(MergePath *best_path, List *tlist, - List *joinclauses, List *otherclauses, - Plan *outer_plan, List *outer_tlist, - Plan *inner_plan, List *inner_tlist); + List *joinclauses, List *otherclauses, + Plan *outer_plan, List *outer_tlist, + Plan *inner_plan, List *inner_tlist); static HashJoin *create_hashjoin_plan(HashPath *best_path, List *tlist, - List *joinclauses, List *otherclauses, - Plan *outer_plan, List *outer_tlist, - Plan *inner_plan, List *inner_tlist); + List *joinclauses, List *otherclauses, + Plan *outer_plan, List *outer_tlist, + Plan *inner_plan, List *inner_tlist); static List *fix_indxqual_references(List *indexquals, IndexPath *index_path); static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, Form_pg_index index); @@ -72,20 +72,20 @@ static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid, static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tideval); static NestLoop *make_nestloop(List *tlist, - List *joinclauses, List *otherclauses, - Plan *lefttree, Plan *righttree, - JoinType jointype); + List *joinclauses, List *otherclauses, + Plan *lefttree, Plan *righttree, + JoinType jointype); static HashJoin *make_hashjoin(List *tlist, - List *joinclauses, List *otherclauses, - List *hashclauses, - Plan *lefttree, Plan *righttree, - JoinType jointype); + List *joinclauses, List *otherclauses, + List *hashclauses, + Plan *lefttree, Plan *righttree, + JoinType jointype); static Hash *make_hash(List *tlist, Node *hashkey, Plan *lefttree); static MergeJoin *make_mergejoin(List *tlist, - List *joinclauses, List *otherclauses, - List *mergeclauses, - Plan *lefttree, Plan *righttree, - JoinType jointype); + List *joinclauses, List *otherclauses, + List *mergeclauses, + Plan *lefttree, Plan *righttree, + JoinType jointype); /* * create_plan @@ -313,8 +313,8 @@ create_append_plan(Query *root, AppendPath *best_path) foreach(subpaths, best_path->subpaths) { - Path *subpath = (Path *) lfirst(subpaths); - + Path *subpath = (Path *) lfirst(subpaths); + subplans = lappend(subplans, create_plan(root, subpath)); } @@ -344,7 +344,7 @@ create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses) /* there should be exactly one base rel involved... */ Assert(length(best_path->parent->relids) == 1); - Assert(! best_path->parent->issubquery); + Assert(!best_path->parent->issubquery); scan_relid = (Index) lfirsti(best_path->parent->relids); @@ -386,7 +386,7 @@ create_indexscan_plan(Query *root, /* there should be exactly one base rel involved... */ Assert(length(best_path->path.parent->relids) == 1); - Assert(! best_path->path.parent->issubquery); + Assert(!best_path->path.parent->issubquery); baserelid = lfirsti(best_path->path.parent->relids); @@ -496,7 +496,7 @@ create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses) /* there should be exactly one base rel involved... */ Assert(length(best_path->path.parent->relids) == 1); - Assert(! best_path->path.parent->issubquery); + Assert(!best_path->path.parent->issubquery); scan_relid = (Index) lfirsti(best_path->path.parent->relids); @@ -737,21 +737,22 @@ create_mergejoin_plan(MergePath *best_path, best_path->innersortkeys); /* - * The executor requires the inner side of a mergejoin to support "mark" - * and "restore" operations. Not all plan types do, so we must be careful - * not to generate an invalid plan. If necessary, an invalid inner plan - * can be handled by inserting a Materialize node. + * The executor requires the inner side of a mergejoin to support + * "mark" and "restore" operations. Not all plan types do, so we must + * be careful not to generate an invalid plan. If necessary, an + * invalid inner plan can be handled by inserting a Materialize node. * - * Since the inner side must be ordered, and only Sorts and IndexScans can - * create order to begin with, you might think there's no problem --- but - * you'd be wrong. Nestloop and merge joins can *preserve* the order of - * their inputs, so they can be selected as the input of a mergejoin, - * and that won't work in the present executor. + * Since the inner side must be ordered, and only Sorts and IndexScans + * can create order to begin with, you might think there's no problem + * --- but you'd be wrong. Nestloop and merge joins can *preserve* + * the order of their inputs, so they can be selected as the input of + * a mergejoin, and that won't work in the present executor. * * Doing this here is a bit of a kluge since the cost of the Materialize - * wasn't taken into account in our earlier decisions. But Materialize - * is hard to estimate a cost for, and the above consideration shows that - * this is a rare case anyway, so this seems an acceptable way to proceed. + * wasn't taken into account in our earlier decisions. But + * Materialize is hard to estimate a cost for, and the above + * consideration shows that this is a rare case anyway, so this seems + * an acceptable way to proceed. * * This check must agree with ExecMarkPos/ExecRestrPos in * executor/execAmi.c! @@ -1015,6 +1016,7 @@ static Node * fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, Oid *opclass) { + /* * Remove any binary-compatible relabeling of the indexkey */ @@ -1025,8 +1027,8 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, * We represent index keys by Var nodes having the varno of the base * table but varattno equal to the index's attribute number (index * column position). This is a bit hokey ... would be cleaner to use - * a special-purpose node type that could not be mistaken for a regular - * Var. But it will do for now. + * a special-purpose node type that could not be mistaken for a + * regular Var. But it will do for now. */ if (IsA(node, Var)) { @@ -1062,7 +1064,7 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, * the returned varattno must be 1. */ - Assert(is_funcclause(node)); /* not a very thorough check, but easy */ + Assert(is_funcclause(node));/* not a very thorough check, but easy */ /* indclass[0] is the only class of a functional index */ *opclass = index->indclass[0]; @@ -1493,7 +1495,7 @@ make_sort_from_pathkeys(List *tlist, Plan *lefttree, List *pathkeys) return make_sort(sort_tlist, lefttree, numsortkeys); } -Material * +Material * make_material(List *tlist, Plan *lefttree) { Material *node = makeNode(Material); @@ -1734,10 +1736,10 @@ make_limit(List *tlist, Plan *lefttree, copy_plan_costsize(plan, lefttree); /* - * If offset/count are constants, adjust the output rows count and costs - * accordingly. This is only a cosmetic issue if we are at top level, - * but if we are building a subquery then it's important to report - * correct info to the outer planner. + * If offset/count are constants, adjust the output rows count and + * costs accordingly. This is only a cosmetic issue if we are at top + * level, but if we are building a subquery then it's important to + * report correct info to the outer planner. */ if (limitOffset && IsA(limitOffset, Const)) { diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 1025a9b7f6b..2b2ebf238fe 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.57 2001/02/16 03:16:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.58 2001/03/22 03:59:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -35,11 +35,11 @@ static void mark_baserels_for_outer_join(Query *root, Relids rels, - Relids outerrels); + Relids outerrels); static void distribute_qual_to_rels(Query *root, Node *clause, - bool ispusheddown, - bool isouterjoin, - Relids qualscope); + bool ispusheddown, + bool isouterjoin, + Relids qualscope); static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo, Relids join_relids); static void add_vars_to_targetlist(Query *root, List *vars); @@ -57,7 +57,7 @@ static void check_hashjoinable(RestrictInfo *restrictinfo); * build_base_rel_tlists * Creates rel nodes for every relation mentioned in the target list * 'tlist' (if a node hasn't already been created) and adds them to - * root->base_rel_list. Creates targetlist entries for each var seen + * root->base_rel_list. Creates targetlist entries for each var seen * in 'tlist' and adds them to the tlist of the appropriate rel node. */ void @@ -118,6 +118,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode) if (IsA(jtnode, RangeTblRef)) { int varno = ((RangeTblRef *) jtnode)->rtindex; + /* This call to get_base_rel does the primary work... */ RelOptInfo *rel = get_base_rel(root, varno); @@ -160,7 +161,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode) * distribute_quals_to_rels * Recursively scan the query's join tree for WHERE and JOIN/ON qual * clauses, and add these to the appropriate RestrictInfo and JoinInfo - * lists belonging to base RelOptInfos. New base rel entries are created + * lists belonging to base RelOptInfos. New base rel entries are created * as needed. Also, base RelOptInfos are marked with outerjoinset * information, to aid in proper positioning of qual clauses that appear * above outer joins. @@ -169,7 +170,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode) * be evaluated at the lowest level where all the variables it mentions are * available. However, we cannot push a qual down into the nullable side(s) * of an outer join since the qual might eliminate matching rows and cause a - * NULL row to be incorrectly emitted by the join. Therefore, rels appearing + * NULL row to be incorrectly emitted by the join. Therefore, rels appearing * within the nullable side(s) of an outer join are marked with * outerjoinset = list of Relids used at the outer join node. * This list will be added to the list of rels referenced by quals using such @@ -228,14 +229,14 @@ distribute_quals_to_rels(Query *root, Node *jtnode) List *qual; /* - * Order of operations here is subtle and critical. First we recurse - * to handle sub-JOINs. Their join quals will be placed without - * regard for whether this level is an outer join, which is correct. - * Then, if we are an outer join, we mark baserels contained within - * the nullable side(s) with our own rel list; this will restrict - * placement of subsequent quals using those rels, including our own - * quals and quals above us in the join tree. - * Finally we place our own join quals. + * Order of operations here is subtle and critical. First we + * recurse to handle sub-JOINs. Their join quals will be placed + * without regard for whether this level is an outer join, which + * is correct. Then, if we are an outer join, we mark baserels + * contained within the nullable side(s) with our own rel list; + * this will restrict placement of subsequent quals using those + * rels, including our own quals and quals above us in the join + * tree. Finally we place our own join quals. */ leftids = distribute_quals_to_rels(root, j->larg); rightids = distribute_quals_to_rels(root, j->rarg); @@ -261,9 +262,10 @@ distribute_quals_to_rels(Query *root, Node *jtnode) isouterjoin = true; break; case JOIN_UNION: + /* - * This is where we fail if upper levels of planner haven't - * rewritten UNION JOIN as an Append ... + * This is where we fail if upper levels of planner + * haven't rewritten UNION JOIN as an Append ... */ elog(ERROR, "UNION JOIN is not implemented yet"); break; @@ -338,12 +340,12 @@ distribute_qual_to_rels(Query *root, Node *clause, bool can_be_equijoin; restrictinfo->clause = (Expr *) clause; - restrictinfo->eval_cost = -1; /* not computed until needed */ + restrictinfo->eval_cost = -1; /* not computed until needed */ restrictinfo->subclauseindices = NIL; restrictinfo->mergejoinoperator = InvalidOid; restrictinfo->left_sortop = InvalidOid; restrictinfo->right_sortop = InvalidOid; - restrictinfo->left_pathkey = NIL; /* not computable yet */ + restrictinfo->left_pathkey = NIL; /* not computable yet */ restrictinfo->right_pathkey = NIL; restrictinfo->hashjoinoperator = InvalidOid; restrictinfo->left_dispersion = -1; /* not computed until needed */ @@ -358,7 +360,7 @@ distribute_qual_to_rels(Query *root, Node *clause, * Cross-check: clause should contain no relids not within its scope. * Otherwise the parser messed up. */ - if (! is_subseti(relids, qualscope)) + if (!is_subseti(relids, qualscope)) elog(ERROR, "JOIN qualification may not refer to other relations"); /* @@ -377,14 +379,14 @@ distribute_qual_to_rels(Query *root, Node *clause, * This ensures that the clause will be evaluated exactly at the level * of joining corresponding to the outer join. * - * For a non-outer-join qual, we can evaluate the qual as soon as - * (1) we have all the rels it mentions, and (2) we are at or above any - * outer joins that can null any of these rels and are below the syntactic - * location of the given qual. To enforce the latter, scan the base rels - * listed in relids, and merge their outer-join lists into the clause's - * own reference list. At the time we are called, the outerjoinset list - * of each baserel will show exactly those outer joins that are below the - * qual in the join tree. + * For a non-outer-join qual, we can evaluate the qual as soon as (1) we + * have all the rels it mentions, and (2) we are at or above any outer + * joins that can null any of these rels and are below the syntactic + * location of the given qual. To enforce the latter, scan the base + * rels listed in relids, and merge their outer-join lists into the + * clause's own reference list. At the time we are called, the + * outerjoinset list of each baserel will show exactly those outer + * joins that are below the qual in the join tree. */ if (isouterjoin) { @@ -396,19 +398,24 @@ distribute_qual_to_rels(Query *root, Node *clause, Relids newrelids = relids; List *relid; - /* We rely on set_unioni to be nondestructive of its input lists... */ + /* + * We rely on set_unioni to be nondestructive of its input + * lists... + */ can_be_equijoin = true; foreach(relid, relids) { RelOptInfo *rel = get_base_rel(root, lfirsti(relid)); if (rel->outerjoinset && - ! is_subseti(rel->outerjoinset, relids)) + !is_subseti(rel->outerjoinset, relids)) { newrelids = set_unioni(newrelids, rel->outerjoinset); + /* - * Because application of the qual will be delayed by outer - * join, we mustn't assume its vars are equal everywhere. + * Because application of the qual will be delayed by + * outer join, we mustn't assume its vars are equal + * everywhere. */ can_be_equijoin = false; } @@ -419,10 +426,11 @@ distribute_qual_to_rels(Query *root, Node *clause, } /* - * Mark the qual as "pushed down" if it can be applied at a level below - * its original syntactic level. This allows us to distinguish original - * JOIN/ON quals from higher-level quals pushed down to the same joinrel. - * A qual originating from WHERE is always considered "pushed down". + * Mark the qual as "pushed down" if it can be applied at a level + * below its original syntactic level. This allows us to distinguish + * original JOIN/ON quals from higher-level quals pushed down to the + * same joinrel. A qual originating from WHERE is always considered + * "pushed down". */ restrictinfo->ispusheddown = ispusheddown || !sameseti(relids, qualscope); @@ -458,10 +466,10 @@ distribute_qual_to_rels(Query *root, Node *clause, * the relid list. Set additional RestrictInfo fields for * joining. * - * We don't bother setting the merge/hashjoin info if we're not - * going to need it. We do want to know about mergejoinable ops - * in any potential equijoin clause (see later in this routine), - * and we ignore enable_mergejoin if isouterjoin is true, because + * We don't bother setting the merge/hashjoin info if we're not going + * to need it. We do want to know about mergejoinable ops in any + * potential equijoin clause (see later in this routine), and we + * ignore enable_mergejoin if isouterjoin is true, because * mergejoin is the only implementation we have for full and right * outer joins. */ @@ -485,6 +493,7 @@ distribute_qual_to_rels(Query *root, Node *clause, } else { + /* * 'clause' references no rels, and therefore we have no place to * attach it. Shouldn't get here if callers are working properly. @@ -493,12 +502,12 @@ distribute_qual_to_rels(Query *root, Node *clause, } /* - * If the clause has a mergejoinable operator, and is not an outer-join - * qualification nor bubbled up due to an outer join, then the two sides - * represent equivalent PathKeyItems for path keys: any path that is - * sorted by one side will also be sorted by the other (as soon as the - * two rels are joined, that is). Record the key equivalence for future - * use. + * If the clause has a mergejoinable operator, and is not an + * outer-join qualification nor bubbled up due to an outer join, then + * the two sides represent equivalent PathKeyItems for path keys: any + * path that is sorted by one side will also be sorted by the other + * (as soon as the two rels are joined, that is). Record the key + * equivalence for future use. */ if (can_be_equijoin && restrictinfo->mergejoinoperator != InvalidOid) add_equijoined_keys(root, restrictinfo); @@ -569,15 +578,16 @@ process_implied_equality(Query *root, Node *item1, Node *item2, Expr *clause; /* - * Currently, since check_mergejoinable only accepts Var = Var clauses, - * we should only see Var nodes here. Would have to work a little - * harder to locate the right rel(s) if more-general mergejoin clauses - * were accepted. + * Currently, since check_mergejoinable only accepts Var = Var + * clauses, we should only see Var nodes here. Would have to work a + * little harder to locate the right rel(s) if more-general mergejoin + * clauses were accepted. */ Assert(IsA(item1, Var)); irel1 = ((Var *) item1)->varno; Assert(IsA(item2, Var)); irel2 = ((Var *) item2)->varno; + /* * If both vars belong to same rel, we need to look at that rel's * baserestrictinfo list. If different rels, each will have a @@ -593,6 +603,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2, restrictlist = joininfo->jinfo_restrictinfo; } + /* * Scan to see if equality is already known. */ @@ -611,6 +622,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2, (equal(item2, left) && equal(item1, right))) return; /* found a matching clause */ } + /* * This equality is new information, so construct a clause * representing it to add to the query data structures. @@ -620,6 +632,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2, eq_operator = compatible_oper("=", ltype, rtype, true); if (!HeapTupleIsValid(eq_operator)) { + /* * Would it be safe to just not add the equality to the query if * we have no suitable equality operator for the combination of @@ -629,6 +642,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2, typeidTypeName(ltype), typeidTypeName(rtype)); } pgopform = (Form_pg_operator) GETSTRUCT(eq_operator); + /* * Let's just make sure this appears to be a compatible operator. */ @@ -641,21 +655,21 @@ process_implied_equality(Query *root, Node *item1, Node *item2, clause = makeNode(Expr); clause->typeOid = BOOLOID; clause->opType = OP_EXPR; - clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */ - InvalidOid, /* opid */ - BOOLOID); /* operator result type */ + clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */ + InvalidOid, /* opid */ + BOOLOID); /* operator result type */ clause->args = makeList2(item1, item2); ReleaseSysCache(eq_operator); /* * Note: we mark the qual "pushed down" to ensure that it can never be - * taken for an original JOIN/ON clause. We also claim it is an outer- - * join clause, which it isn't, but that keeps distribute_qual_to_rels - * from examining the outerjoinsets of the relevant rels (which are no - * longer of interest, but could keep the qual from being pushed down - * to where it should be). It'll also save a useless call to - * add_equijoined keys... + * taken for an original JOIN/ON clause. We also claim it is an + * outer- join clause, which it isn't, but that keeps + * distribute_qual_to_rels from examining the outerjoinsets of the + * relevant rels (which are no longer of interest, but could keep the + * qual from being pushed down to where it should be). It'll also + * save a useless call to add_equijoined keys... */ distribute_qual_to_rels(root, (Node *) clause, true, true, diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index d196e755d66..b2b362e84a5 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.63 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.64 2001/03/22 03:59:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,7 +33,7 @@ static Plan *subplanner(Query *root, List *flat_tlist, - double tuple_fraction); + double tuple_fraction); /*-------------------- @@ -82,7 +82,7 @@ query_planner(Query *root, /* * If the query has an empty join tree, then it's something easy like - * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly. + * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly. */ if (root->jointree->fromlist == NIL) { @@ -213,9 +213,9 @@ subplanner(Query *root, foreach(brel, root->base_rel_list) { RelOptInfo *baserel = (RelOptInfo *) lfirst(brel); - int relid = lfirsti(baserel->relids); + int relid = lfirsti(baserel->relids); - if (! ptrMember(baserel, joined_rels)) + if (!ptrMember(baserel, joined_rels)) elog(ERROR, "Internal error: no jointree entry for rel %s (%d)", rt_fetch(relid, root->rtable)->eref->relname, relid); } @@ -334,9 +334,9 @@ subplanner(Query *root, /* * Nothing for it but to sort the cheapest-total-cost path --- but we * let the caller do that. grouping_planner has to be able to add a - * sort node anyway, so no need for extra code here. (Furthermore, the - * given pathkeys might involve something we can't compute here, such - * as an aggregate function...) + * sort node anyway, so no need for extra code here. (Furthermore, + * the given pathkeys might involve something we can't compute here, + * such as an aggregate function...) */ root->query_pathkeys = cheapestpath->pathkeys; resultplan = create_plan(root, cheapestpath); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 9faf6b95e80..c5bd439587e 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.101 2001/01/27 04:42:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.102 2001/03/22 03:59:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,9 +33,9 @@ /* Expression kind codes for preprocess_expression */ -#define EXPRKIND_TARGET 0 +#define EXPRKIND_TARGET 0 #define EXPRKIND_WHERE 1 -#define EXPRKIND_HAVING 2 +#define EXPRKIND_HAVING 2 static Node *pull_up_subqueries(Query *parse, Node *jtnode); @@ -68,16 +68,16 @@ planner(Query *parse) /* * The planner can be called recursively (an example is when - * eval_const_expressions tries to pre-evaluate an SQL function). - * So, these global state variables must be saved and restored. + * eval_const_expressions tries to pre-evaluate an SQL function). So, + * these global state variables must be saved and restored. * - * These vars cannot be moved into the Query structure since their - * whole purpose is communication across multiple sub-Queries. + * These vars cannot be moved into the Query structure since their whole + * purpose is communication across multiple sub-Queries. * * Note we do NOT save and restore PlannerPlanId: it exists to assign - * unique IDs to SubPlan nodes, and we want those IDs to be unique - * for the life of a backend. Also, PlannerInitPlan is saved/restored - * in subquery_planner, not here. + * unique IDs to SubPlan nodes, and we want those IDs to be unique for + * the life of a backend. Also, PlannerInitPlan is saved/restored in + * subquery_planner, not here. */ save_PlannerQueryLevel = PlannerQueryLevel; save_PlannerParamVar = PlannerParamVar; @@ -150,6 +150,7 @@ subquery_planner(Query *parse, double tuple_fraction) */ parse->jointree = (FromExpr *) pull_up_subqueries(parse, (Node *) parse->jointree); + /* * If so, we may have created opportunities to simplify the jointree. */ @@ -170,26 +171,26 @@ subquery_planner(Query *parse, double tuple_fraction) /* * A HAVING clause without aggregates is equivalent to a WHERE clause - * (except it can only refer to grouped fields). Transfer any agg-free - * clauses of the HAVING qual into WHERE. This may seem like wasting - * cycles to cater to stupidly-written queries, but there are other - * reasons for doing it. Firstly, if the query contains no aggs at all, - * then we aren't going to generate an Agg plan node, and so there'll be - * no place to execute HAVING conditions; without this transfer, we'd - * lose the HAVING condition entirely, which is wrong. Secondly, when - * we push down a qual condition into a sub-query, it's easiest to push - * the qual into HAVING always, in case it contains aggs, and then let - * this code sort it out. + * (except it can only refer to grouped fields). Transfer any + * agg-free clauses of the HAVING qual into WHERE. This may seem like + * wasting cycles to cater to stupidly-written queries, but there are + * other reasons for doing it. Firstly, if the query contains no aggs + * at all, then we aren't going to generate an Agg plan node, and so + * there'll be no place to execute HAVING conditions; without this + * transfer, we'd lose the HAVING condition entirely, which is wrong. + * Secondly, when we push down a qual condition into a sub-query, it's + * easiest to push the qual into HAVING always, in case it contains + * aggs, and then let this code sort it out. * * Note that both havingQual and parse->jointree->quals are in * implicitly-ANDed-list form at this point, even though they are - * declared as Node *. Also note that contain_agg_clause does not + * declared as Node *. Also note that contain_agg_clause does not * recurse into sub-selects, which is exactly what we need here. */ newHaving = NIL; foreach(lst, (List *) parse->havingQual) { - Node *havingclause = (Node *) lfirst(lst); + Node *havingclause = (Node *) lfirst(lst); if (contain_agg_clause(havingclause)) newHaving = lappend(newHaving, havingclause); @@ -201,30 +202,32 @@ subquery_planner(Query *parse, double tuple_fraction) /* * Do the main planning. If we have an inherited target relation, - * that needs special processing, else go straight to grouping_planner. + * that needs special processing, else go straight to + * grouping_planner. */ if (parse->resultRelation && - (lst = expand_inherted_rtentry(parse, parse->resultRelation)) != NIL) + (lst = expand_inherted_rtentry(parse, parse->resultRelation)) != NIL) plan = inheritance_planner(parse, lst); else plan = grouping_planner(parse, tuple_fraction); /* - * If any subplans were generated, or if we're inside a subplan, - * build subPlan, extParam and locParam lists for plan nodes. + * If any subplans were generated, or if we're inside a subplan, build + * subPlan, extParam and locParam lists for plan nodes. */ if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1) { (void) SS_finalize_plan(plan); + /* - * At the moment, SS_finalize_plan doesn't handle initPlans - * and so we assign them to the topmost plan node. + * At the moment, SS_finalize_plan doesn't handle initPlans and so + * we assign them to the topmost plan node. */ plan->initPlan = PlannerInitPlan; /* Must add the initPlans' extParams to the topmost node's, too */ foreach(lst, plan->initPlan) { - SubPlan *subplan = (SubPlan *) lfirst(lst); + SubPlan *subplan = (SubPlan *) lfirst(lst); plan->extParam = set_unioni(plan->extParam, subplan->plan->extParam); @@ -266,44 +269,47 @@ pull_up_subqueries(Query *parse, Node *jtnode) Query *subquery = rte->subquery; /* - * Is this a subquery RTE, and if so, is the subquery simple enough - * to pull up? (If not, do nothing at this node.) + * Is this a subquery RTE, and if so, is the subquery simple + * enough to pull up? (If not, do nothing at this node.) */ if (subquery && is_simple_subquery(subquery)) { - int rtoffset; - Node *subjointree; - List *subtlist; - List *l; + int rtoffset; + Node *subjointree; + List *subtlist; + List *l; /* - * First, recursively pull up the subquery's subqueries, - * so that this routine's processing is complete for its - * jointree and rangetable. NB: if the same subquery is - * referenced from multiple jointree items (which can't happen - * normally, but might after rule rewriting), then we will invoke - * this processing multiple times on that subquery. OK because + * First, recursively pull up the subquery's subqueries, so + * that this routine's processing is complete for its jointree + * and rangetable. NB: if the same subquery is referenced + * from multiple jointree items (which can't happen normally, + * but might after rule rewriting), then we will invoke this + * processing multiple times on that subquery. OK because * nothing will happen after the first time. We do have to be * careful to copy everything we pull up, however, or risk * having chunks of structure multiply linked. */ subquery->jointree = (FromExpr *) pull_up_subqueries(subquery, (Node *) subquery->jointree); + /* - * Append the subquery's rangetable to mine (currently, - * no adjustments will be needed in the subquery's rtable). + * Append the subquery's rangetable to mine (currently, no + * adjustments will be needed in the subquery's rtable). */ rtoffset = length(parse->rtable); parse->rtable = nconc(parse->rtable, copyObject(subquery->rtable)); + /* - * Make copies of the subquery's jointree and targetlist - * with varnos adjusted to match the merged rangetable. + * Make copies of the subquery's jointree and targetlist with + * varnos adjusted to match the merged rangetable. */ subjointree = copyObject(subquery->jointree); OffsetVarNodes(subjointree, rtoffset, 0); subtlist = copyObject(subquery->targetList); OffsetVarNodes((Node *) subtlist, rtoffset, 0); + /* * Replace all of the top query's references to the subquery's * outputs with copies of the adjusted subtlist items, being @@ -316,16 +322,18 @@ pull_up_subqueries(Query *parse, Node *jtnode) parse->havingQual = ResolveNew(parse->havingQual, varno, 0, subtlist, CMD_SELECT, 0); + /* * Pull up any FOR UPDATE markers, too. */ foreach(l, subquery->rowMarks) { - int submark = lfirsti(l); + int submark = lfirsti(l); parse->rowMarks = lappendi(parse->rowMarks, submark + rtoffset); } + /* * Miscellaneous housekeeping. */ @@ -345,9 +353,7 @@ pull_up_subqueries(Query *parse, Node *jtnode) List *l; foreach(l, f->fromlist) - { lfirst(l) = pull_up_subqueries(parse, lfirst(l)); - } } else if (IsA(jtnode, JoinExpr)) { @@ -370,6 +376,7 @@ pull_up_subqueries(Query *parse, Node *jtnode) static bool is_simple_subquery(Query *subquery) { + /* * Let's just make sure it's a valid subselect ... */ @@ -379,12 +386,14 @@ is_simple_subquery(Query *subquery) subquery->into != NULL || subquery->isPortal) elog(ERROR, "is_simple_subquery: subquery is bogus"); + /* - * Can't currently pull up a query with setops. - * Maybe after querytree redesign... + * Can't currently pull up a query with setops. Maybe after querytree + * redesign... */ if (subquery->setOperations) return false; + /* * Can't pull up a subquery involving grouping, aggregation, sorting, * or limiting. @@ -397,12 +406,13 @@ is_simple_subquery(Query *subquery) subquery->limitOffset || subquery->limitCount) return false; + /* * Hack: don't try to pull up a subquery with an empty jointree. * query_planner() will correctly generate a Result plan for a * jointree that's totally empty, but I don't think the right things - * happen if an empty FromExpr appears lower down in a jointree. - * Not worth working hard on this, just to collapse SubqueryScan/Result + * happen if an empty FromExpr appears lower down in a jointree. Not + * worth working hard on this, just to collapse SubqueryScan/Result * into Result... */ if (subquery->jointree->fromlist == NIL) @@ -443,7 +453,9 @@ resolvenew_in_jointree(Node *jtnode, int varno, List *subtlist) resolvenew_in_jointree(j->rarg, varno, subtlist); j->quals = ResolveNew(j->quals, varno, 0, subtlist, CMD_SELECT, 0); - /* We don't bother to update the colvars list, since it won't be + + /* + * We don't bother to update the colvars list, since it won't be * used again ... */ } @@ -458,13 +470,13 @@ resolvenew_in_jointree(Node *jtnode, int varno, List *subtlist) * * If we succeed in pulling up a subquery then we might form a jointree * in which a FromExpr is a direct child of another FromExpr. In that - * case we can consider collapsing the two FromExprs into one. This is + * case we can consider collapsing the two FromExprs into one. This is * an optional conversion, since the planner will work correctly either * way. But we may find a better plan (at the cost of more planning time) * if we merge the two nodes. * * NOTE: don't try to do this in the same jointree scan that does subquery - * pullup! Since we're changing the jointree structure here, that wouldn't + * pullup! Since we're changing the jointree structure here, that wouldn't * work reliably --- see comments for pull_up_subqueries(). */ static Node * @@ -484,27 +496,29 @@ preprocess_jointree(Query *parse, Node *jtnode) foreach(l, f->fromlist) { - Node *child = (Node *) lfirst(l); + Node *child = (Node *) lfirst(l); /* Recursively simplify the child... */ child = preprocess_jointree(parse, child); /* Now, is it a FromExpr? */ if (child && IsA(child, FromExpr)) { + /* - * Yes, so do we want to merge it into parent? Always do so - * if child has just one element (since that doesn't make the - * parent's list any longer). Otherwise we have to be careful - * about the increase in planning time caused by combining the - * two join search spaces into one. Our heuristic is to merge - * if the merge will produce a join list no longer than - * GEQO_RELS/2. (Perhaps need an additional user parameter?) + * Yes, so do we want to merge it into parent? Always do + * so if child has just one element (since that doesn't + * make the parent's list any longer). Otherwise we have + * to be careful about the increase in planning time + * caused by combining the two join search spaces into + * one. Our heuristic is to merge if the merge will + * produce a join list no longer than GEQO_RELS/2. + * (Perhaps need an additional user parameter?) */ FromExpr *subf = (FromExpr *) child; int childlen = length(subf->fromlist); int myothers = length(newlist) + length(lnext(l)); - if (childlen <= 1 || (childlen+myothers) <= geqo_rels/2) + if (childlen <= 1 || (childlen + myothers) <= geqo_rels / 2) { newlist = nconc(newlist, subf->fromlist); f->quals = make_and_qual(f->quals, subf->quals); @@ -540,6 +554,7 @@ preprocess_jointree(Query *parse, Node *jtnode) static Node * preprocess_expression(Query *parse, Node *expr, int kind) { + /* * Simplify constant expressions. * @@ -551,8 +566,8 @@ preprocess_expression(Query *parse, Node *expr, int kind) expr = eval_const_expressions(expr); /* - * If it's a qual or havingQual, canonicalize it, and convert it - * to implicit-AND format. + * If it's a qual or havingQual, canonicalize it, and convert it to + * implicit-AND format. * * XXX Is there any value in re-applying eval_const_expressions after * canonicalize_qual? @@ -575,10 +590,11 @@ preprocess_expression(Query *parse, Node *expr, int kind) if (kind != EXPRKIND_WHERE && (parse->groupClause != NIL || parse->hasAggs)) { + /* * Check for ungrouped variables passed to subplans. Note we - * do NOT do this for subplans in WHERE (or JOIN/ON); it's legal - * there because WHERE is evaluated pre-GROUP. + * do NOT do this for subplans in WHERE (or JOIN/ON); it's + * legal there because WHERE is evaluated pre-GROUP. */ check_subplans_for_ungrouped_vars(expr, parse); } @@ -635,12 +651,12 @@ preprocess_qual_conditions(Query *parse, Node *jtnode) * inheritance set. * * We have to handle this case differently from cases where a source - * relation is an inheritance set. Source inheritance is expanded at + * relation is an inheritance set. Source inheritance is expanded at * the bottom of the plan tree (see allpaths.c), but target inheritance * has to be expanded at the top. The reason is that for UPDATE, each * target relation needs a different targetlist matching its own column * set. (This is not so critical for DELETE, but for simplicity we treat - * inherited DELETE the same way.) Fortunately, the UPDATE/DELETE target + * inherited DELETE the same way.) Fortunately, the UPDATE/DELETE target * can never be the nullable side of an outer join, so it's OK to generate * the plan this way. * @@ -661,17 +677,17 @@ inheritance_planner(Query *parse, List *inheritlist) foreach(l, inheritlist) { - int childRTindex = lfirsti(l); - Oid childOID = getrelid(childRTindex, parse->rtable); - Query *subquery; - Plan *subplan; + int childRTindex = lfirsti(l); + Oid childOID = getrelid(childRTindex, parse->rtable); + Query *subquery; + Plan *subplan; /* Generate modified query with this rel as target */ subquery = (Query *) adjust_inherited_attrs((Node *) parse, - parentRTindex, parentOID, - childRTindex, childOID); + parentRTindex, parentOID, + childRTindex, childOID); /* Generate plan */ - subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */); + subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ ); subplans = lappend(subplans, subplan); /* Save preprocessed tlist from first rel for use in Append */ if (tlist == NIL) @@ -718,6 +734,7 @@ grouping_planner(Query *parse, double tuple_fraction) if (parse->setOperations) { + /* * Construct the plan for set operations. The result will not * need any work except perhaps a top-level sort and/or LIMIT. @@ -736,17 +753,17 @@ grouping_planner(Query *parse, double tuple_fraction) tlist = postprocess_setop_tlist(result_plan->targetlist, tlist); /* - * Can't handle FOR UPDATE here (parser should have checked already, - * but let's make sure). + * Can't handle FOR UPDATE here (parser should have checked + * already, but let's make sure). */ if (parse->rowMarks) elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT"); /* * We set current_pathkeys NIL indicating we do not know sort - * order. This is correct when the top set operation is UNION ALL, - * since the appended-together results are unsorted even if the - * subplans were sorted. For other set operations we could be + * order. This is correct when the top set operation is UNION + * ALL, since the appended-together results are unsorted even if + * the subplans were sorted. For other set operations we could be * smarter --- room for future improvement! */ current_pathkeys = NIL; @@ -772,22 +789,26 @@ grouping_planner(Query *parse, double tuple_fraction) /* * Add TID targets for rels selected FOR UPDATE (should this be - * done in preprocess_targetlist?). The executor uses the TID - * to know which rows to lock, much as for UPDATE or DELETE. + * done in preprocess_targetlist?). The executor uses the TID to + * know which rows to lock, much as for UPDATE or DELETE. */ if (parse->rowMarks) { List *l; /* - * We've got trouble if the FOR UPDATE appears inside grouping, - * since grouping renders a reference to individual tuple CTIDs - * invalid. This is also checked at parse time, but that's - * insufficient because of rule substitution, query pullup, etc. + * We've got trouble if the FOR UPDATE appears inside + * grouping, since grouping renders a reference to individual + * tuple CTIDs invalid. This is also checked at parse time, + * but that's insufficient because of rule substitution, query + * pullup, etc. */ CheckSelectForUpdate(parse); - /* Currently the executor only supports FOR UPDATE at top level */ + /* + * Currently the executor only supports FOR UPDATE at top + * level + */ if (PlannerQueryLevel > 1) elog(ERROR, "SELECT FOR UPDATE is not allowed in subselects"); @@ -873,9 +894,9 @@ grouping_planner(Query *parse, double tuple_fraction) int32 count = DatumGetInt32(limitc->constvalue); /* - * A NULL-constant LIMIT represents "LIMIT ALL", - * which we treat the same as no limit (ie, - * expect to retrieve all the tuples). + * A NULL-constant LIMIT represents "LIMIT ALL", which + * we treat the same as no limit (ie, expect to + * retrieve all the tuples). */ if (!limitc->constisnull && count > 0) { @@ -902,17 +923,19 @@ grouping_planner(Query *parse, double tuple_fraction) } else { + /* - * COUNT is an expression ... don't know exactly what the - * limit will be, but for lack of a better idea assume - * 10% of the plan's result is wanted. + * COUNT is an expression ... don't know exactly what + * the limit will be, but for lack of a better idea + * assume 10% of the plan's result is wanted. */ tuple_fraction = 0.10; } } /* - * If no LIMIT, check for retrieve-into-portal, ie DECLARE CURSOR. + * If no LIMIT, check for retrieve-into-portal, ie DECLARE + * CURSOR. * * We have no real idea how many tuples the user will ultimately * FETCH from a cursor, but it seems a good bet that he diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 1f2ae69561b..e7f8361b9a7 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.70 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.71 2001/03/22 03:59:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -97,16 +97,17 @@ set_plan_references(Plan *plan) fix_expr_references(plan, (Node *) ((IndexScan *) plan)->indxqual); fix_expr_references(plan, - (Node *) ((IndexScan *) plan)->indxqualorig); + (Node *) ((IndexScan *) plan)->indxqualorig); break; case T_TidScan: fix_expr_references(plan, (Node *) plan->targetlist); fix_expr_references(plan, (Node *) plan->qual); break; case T_SubqueryScan: + /* - * We do not do set_uppernode_references() here, because - * a SubqueryScan will always have been created with correct + * We do not do set_uppernode_references() here, because a + * SubqueryScan will always have been created with correct * references to its subplan's outputs to begin with. */ fix_expr_references(plan, (Node *) plan->targetlist); @@ -126,7 +127,7 @@ set_plan_references(Plan *plan) fix_expr_references(plan, (Node *) plan->qual); fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual); fix_expr_references(plan, - (Node *) ((MergeJoin *) plan)->mergeclauses); + (Node *) ((MergeJoin *) plan)->mergeclauses); break; case T_HashJoin: set_join_references((Join *) plan); @@ -134,7 +135,7 @@ set_plan_references(Plan *plan) fix_expr_references(plan, (Node *) plan->qual); fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual); fix_expr_references(plan, - (Node *) ((HashJoin *) plan)->hashclauses); + (Node *) ((HashJoin *) plan)->hashclauses); break; case T_Material: case T_Sort: @@ -148,10 +149,10 @@ set_plan_references(Plan *plan) * targetlists or quals (because they just return their * unmodified input tuples). The optimizer is lazy about * creating really valid targetlists for them. Best to just - * leave the targetlist alone. In particular, we do not want + * leave the targetlist alone. In particular, we do not want * to pull a subplan list for them, since we will likely end - * up with duplicate list entries for subplans that also appear - * in lower levels of the plan tree! + * up with duplicate list entries for subplans that also + * appear in lower levels of the plan tree! */ break; case T_Agg: @@ -175,11 +176,12 @@ set_plan_references(Plan *plan) fix_expr_references(plan, ((Result *) plan)->resconstantqual); break; case T_Append: + /* * Append, like Sort et al, doesn't actually evaluate its - * targetlist or quals, and we haven't bothered to give it - * its own tlist copy. So, don't fix targetlist/qual. - * But do recurse into subplans. + * targetlist or quals, and we haven't bothered to give it its + * own tlist copy. So, don't fix targetlist/qual. But do + * recurse into subplans. */ foreach(pl, ((Append *) plan)->appendplans) set_plan_references((Plan *) lfirst(pl)); @@ -296,7 +298,7 @@ set_uppernode_references(Plan *plan, Index subvarno) subplanTargetList = NIL; outputTargetList = NIL; - foreach (l, plan->targetlist) + foreach(l, plan->targetlist) { TargetEntry *tle = (TargetEntry *) lfirst(l); TargetEntry *subplantle; @@ -306,8 +308,8 @@ set_uppernode_references(Plan *plan, Index subvarno) if (subplantle) { /* Found a matching subplan output expression */ - Resdom *resdom = subplantle->resdom; - Var *newvar; + Resdom *resdom = subplantle->resdom; + Var *newvar; newvar = makeVar(subvarno, resdom->resno, @@ -317,7 +319,7 @@ set_uppernode_references(Plan *plan, Index subvarno) /* If we're just copying a simple Var, copy up original info */ if (subplantle->expr && IsA(subplantle->expr, Var)) { - Var *subvar = (Var *) subplantle->expr; + Var *subvar = (Var *) subplantle->expr; newvar->varnoold = subvar->varnoold; newvar->varoattno = subvar->varoattno; diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 0a7d4926b76..9d47b60430a 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.48 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.49 2001/03/22 03:59:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -82,12 +82,12 @@ replace_var(Var *var) /* * If there's already a PlannerParamVar entry for this same Var, just - * use it. NOTE: in sufficiently complex querytrees, it is - * possible for the same varno/varlevel to refer to different RTEs in - * different parts of the parsetree, so that different fields might - * end up sharing the same Param number. As long as we check the - * vartype as well, I believe that this sort of aliasing will cause no - * trouble. The correct field should get stored into the Param slot at + * use it. NOTE: in sufficiently complex querytrees, it is possible + * for the same varno/varlevel to refer to different RTEs in different + * parts of the parsetree, so that different fields might end up + * sharing the same Param number. As long as we check the vartype as + * well, I believe that this sort of aliasing will cause no trouble. + * The correct field should get stored into the Param slot at * execution in each part of the tree. */ i = 0; @@ -142,10 +142,10 @@ make_subplan(SubLink *slink) elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)"); /* - * Copy the source Query node. This is a quick and dirty kluge to resolve - * the fact that the parser can generate trees with multiple links to the - * same sub-Query node, but the planner wants to scribble on the Query. - * Try to clean this up when we do querytree redesign... + * Copy the source Query node. This is a quick and dirty kluge to + * resolve the fact that the parser can generate trees with multiple + * links to the same sub-Query node, but the planner wants to scribble + * on the Query. Try to clean this up when we do querytree redesign... */ subquery = (Query *) copyObject(subquery); @@ -183,7 +183,8 @@ make_subplan(SubLink *slink) */ node->plan = plan = subquery_planner(subquery, tuple_fraction); - node->plan_id = PlannerPlanId++; /* Assign unique ID to this SubPlan */ + node->plan_id = PlannerPlanId++; /* Assign unique ID to this + * SubPlan */ node->rtable = subquery->rtable; node->sublink = slink; @@ -191,8 +192,8 @@ make_subplan(SubLink *slink) slink->subselect = NULL; /* cool ?! see error check above! */ /* - * Make parParam list of params that current query level will pass - * to this child plan. + * Make parParam list of params that current query level will pass to + * this child plan. */ foreach(lst, plan->extParam) { @@ -275,7 +276,7 @@ make_subplan(SubLink *slink) tup = SearchSysCache(OPEROID, ObjectIdGetDatum(oper->opno), 0, 0, 0); - if (! HeapTupleIsValid(tup)) + if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for operator %u", oper->opno); opform = (Form_pg_operator) GETSTRUCT(tup); @@ -413,7 +414,7 @@ make_subplan(SubLink *slink) tup = SearchSysCache(OPEROID, ObjectIdGetDatum(oper->opno), 0, 0, 0); - if (! HeapTupleIsValid(tup)) + if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for operator %u", oper->opno); opform = (Form_pg_operator) GETSTRUCT(tup); @@ -614,15 +615,16 @@ SS_finalize_plan(Plan *plan) break; case T_SubqueryScan: + /* - * In a SubqueryScan, SS_finalize_plan has already been run - * on the subplan by the inner invocation of subquery_planner, - * so there's no need to do it again. Instead, just pull out - * the subplan's extParams list, which represents the params - * it needs from my level and higher levels. + * In a SubqueryScan, SS_finalize_plan has already been run on + * the subplan by the inner invocation of subquery_planner, so + * there's no need to do it again. Instead, just pull out the + * subplan's extParams list, which represents the params it + * needs from my level and higher levels. */ results.paramids = set_unioni(results.paramids, - ((SubqueryScan *) plan)->subplan->extParam); + ((SubqueryScan *) plan)->subplan->extParam); break; case T_IndexScan: diff --git a/src/backend/optimizer/prep/prepkeyset.c b/src/backend/optimizer/prep/prepkeyset.c index 64d1d818108..180637d099e 100644 --- a/src/backend/optimizer/prep/prepkeyset.c +++ b/src/backend/optimizer/prep/prepkeyset.c @@ -104,7 +104,8 @@ transformKeySetQuery(Query *origNode) Node_Copy(origNode, unionNode, distinctClause); Node_Copy(origNode, unionNode, sortClause); Node_Copy(origNode, unionNode, rtable); - origNode->jointree->quals = NULL; /* avoid unnecessary copying */ + origNode->jointree->quals = NULL; /* avoid unnecessary + * copying */ Node_Copy(origNode, unionNode, jointree); Node_Copy(origNode, unionNode, targetList); @@ -216,4 +217,4 @@ inspectOpNode(Expr *expr) return (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const); } -#endif /* ENABLE_KEY_SET_QUERY */ +#endif /* ENABLE_KEY_SET_QUERY */ diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c index 6fa9c4db29e..2dc92deca17 100644 --- a/src/backend/optimizer/prep/prepqual.c +++ b/src/backend/optimizer/prep/prepqual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.28 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.29 2001/03/22 03:59:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -260,6 +260,7 @@ dnfify(Expr *qual) return newqual; } + #endif /*-------------------- @@ -663,11 +664,11 @@ or_normalize(List *orlist) * We are going to insert the orlist into multiple places in the * result expression. For most expression types, it'd be OK to * just have multiple links to the same subtree, but this fails - * badly for SubLinks (and perhaps other cases?). For safety, - * we make a distinct copy for each place the orlist is inserted. + * badly for SubLinks (and perhaps other cases?). For safety, we + * make a distinct copy for each place the orlist is inserted. */ if (lnext(temp) == NIL) - neworlist = orlist; /* can use original tree at the end */ + neworlist = orlist; /* can use original tree at the end */ else neworlist = copyObject(orlist); @@ -791,11 +792,12 @@ and_normalize(List *andlist) * We are going to insert the andlist into multiple places in the * result expression. For most expression types, it'd be OK to * just have multiple links to the same subtree, but this fails - * badly for SubLinks (and perhaps other cases?). For safety, - * we make a distinct copy for each place the andlist is inserted. + * badly for SubLinks (and perhaps other cases?). For safety, we + * make a distinct copy for each place the andlist is inserted. */ if (lnext(temp) == NIL) - newandlist = andlist; /* can use original tree at the end */ + newandlist = andlist; /* can use original tree at the + * end */ else newandlist = copyObject(andlist); @@ -957,8 +959,10 @@ count_bool_nodes(Expr *qual, } else if (contain_subplans((Node *) qual)) { - /* charge extra for subexpressions containing sub-SELECTs, - * to discourage us from rearranging them in a way that might + + /* + * charge extra for subexpressions containing sub-SELECTs, to + * discourage us from rearranging them in a way that might * generate N copies of a subselect rather than one. The magic * constant here interacts with the "4x maximum growth" heuristic * in canonicalize_qual(). diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index f8a5afbbc45..da51a76d3f3 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.41 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.42 2001/03/22 03:59:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,8 +33,8 @@ static List *expand_targetlist(List *tlist, int command_type, Index result_relation, List *range_table); static TargetEntry *process_matched_tle(TargetEntry *src_tle, - TargetEntry *prior_tle, - int attrno); + TargetEntry *prior_tle, + int attrno); /* @@ -49,9 +49,10 @@ preprocess_targetlist(List *tlist, Index result_relation, List *range_table) { + /* - * Sanity check: if there is a result relation, it'd better be a - * real relation not a subquery. Else parser or rewriter messed up. + * Sanity check: if there is a result relation, it'd better be a real + * relation not a subquery. Else parser or rewriter messed up. */ if (result_relation) { @@ -250,7 +251,7 @@ expand_targetlist(List *tlist, int command_type, new_tle = makeTargetEntry(makeResdom(attrno, atttype, atttypmod, - pstrdup(attrname), + pstrdup(attrname), false), (Node *) temp_var); break; @@ -280,7 +281,7 @@ expand_targetlist(List *tlist, int command_type, { Resdom *resdom = old_tle->resdom; - if (! resdom->resjunk) + if (!resdom->resjunk) elog(ERROR, "Unexpected assignment to attribute \"%s\"", resdom->resname); /* Get the resno right, but don't copy unnecessarily */ @@ -314,9 +315,10 @@ expand_targetlist(List *tlist, int command_type, * Essentially, the expression we want to produce in this case is like * foo = array_set(array_set(foo, 2, 42), 4, 43) */ -static TargetEntry *process_matched_tle(TargetEntry *src_tle, - TargetEntry *prior_tle, - int attrno) +static TargetEntry * +process_matched_tle(TargetEntry *src_tle, + TargetEntry *prior_tle, + int attrno) { Resdom *resdom = src_tle->resdom; Node *priorbottom; @@ -324,11 +326,13 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle, if (prior_tle == NULL) { + /* - * Normal case where this is the first assignment to the attribute. + * Normal case where this is the first assignment to the + * attribute. * - * We can recycle the old TLE+resdom if right resno; else make a - * new one to avoid modifying the old tlist structure. (Is preserving + * We can recycle the old TLE+resdom if right resno; else make a new + * one to avoid modifying the old tlist structure. (Is preserving * old tlist actually necessary? Not sure, be safe.) */ if (resdom->resno == attrno) @@ -339,7 +343,7 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle, } /* - * Multiple assignments to same attribute. Allow only if all are + * Multiple assignments to same attribute. Allow only if all are * array-assign operators with same bottom array object. */ if (src_tle->expr == NULL || !IsA(src_tle->expr, ArrayRef) || @@ -350,16 +354,19 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle, ((ArrayRef *) prior_tle->expr)->refelemtype) elog(ERROR, "Multiple assignments to same attribute \"%s\"", resdom->resname); + /* - * Prior TLE could be a nest of ArrayRefs if we do this more than once. + * Prior TLE could be a nest of ArrayRefs if we do this more than + * once. */ priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr; while (priorbottom != NULL && IsA(priorbottom, ArrayRef) && ((ArrayRef *) priorbottom)->refassgnexpr != NULL) priorbottom = ((ArrayRef *) priorbottom)->refexpr; - if (! equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr)) + if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr)) elog(ERROR, "Multiple assignments to same attribute \"%s\"", resdom->resname); + /* * Looks OK to nest 'em. */ diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 85058757e5e..968b9ded780 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -5,7 +5,7 @@ * from a time when only UNIONs were implemented. * * There is also some code here to support planning of queries that use - * inheritance (SELECT FROM foo*). This no longer has much connection + * inheritance (SELECT FROM foo*). This no longer has much connection * to the processing of UNION queries, but it's still here. * * @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.60 2001/01/24 19:42:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.61 2001/03/22 03:59:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -50,22 +50,22 @@ typedef struct } adjust_inherited_attrs_context; static Plan *recurse_set_operations(Node *setOp, Query *parse, - List *colTypes, bool junkOK, - int flag, List *refnames_tlist); + List *colTypes, bool junkOK, + int flag, List *refnames_tlist); static Plan *generate_union_plan(SetOperationStmt *op, Query *parse, - List *refnames_tlist); + List *refnames_tlist); static Plan *generate_nonunion_plan(SetOperationStmt *op, Query *parse, - List *refnames_tlist); + List *refnames_tlist); static List *recurse_union_children(Node *setOp, Query *parse, - SetOperationStmt *top_union, - List *refnames_tlist); + SetOperationStmt *top_union, + List *refnames_tlist); static List *generate_setop_tlist(List *colTypes, int flag, - bool hack_constants, - List *input_tlist, - List *refnames_tlist); + bool hack_constants, + List *input_tlist, + List *refnames_tlist); static bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK); static Node *adjust_inherited_attrs_mutator(Node *node, - adjust_inherited_attrs_context *context); + adjust_inherited_attrs_context *context); /* @@ -99,10 +99,10 @@ plan_set_operations(Query *parse) Assert(leftmostQuery != NULL); /* - * Recurse on setOperations tree to generate plans for set ops. - * The final output plan should have just the column types shown - * as the output from the top-level node, plus possibly a resjunk - * working column (we can rely on upper-level nodes to deal with that). + * Recurse on setOperations tree to generate plans for set ops. The + * final output plan should have just the column types shown as the + * output from the top-level node, plus possibly a resjunk working + * column (we can rely on upper-level nodes to deal with that). */ return recurse_set_operations((Node *) topop, parse, topop->colTypes, true, -1, @@ -127,16 +127,18 @@ recurse_set_operations(Node *setOp, Query *parse, { RangeTblRef *rtr = (RangeTblRef *) setOp; RangeTblEntry *rte = rt_fetch(rtr->rtindex, parse->rtable); - Query *subquery = rte->subquery; - Plan *subplan, - *plan; + Query *subquery = rte->subquery; + Plan *subplan, + *plan; Assert(subquery != NULL); + /* * Generate plan for primitive subquery */ subplan = subquery_planner(subquery, -1.0 /* default case */ ); + /* * Add a SubqueryScan with the caller-requested targetlist */ @@ -152,28 +154,30 @@ recurse_set_operations(Node *setOp, Query *parse, else if (IsA(setOp, SetOperationStmt)) { SetOperationStmt *op = (SetOperationStmt *) setOp; - Plan *plan; + Plan *plan; /* UNIONs are much different from INTERSECT/EXCEPT */ if (op->op == SETOP_UNION) plan = generate_union_plan(op, parse, refnames_tlist); else plan = generate_nonunion_plan(op, parse, refnames_tlist); + /* * If necessary, add a Result node to project the caller-requested * output columns. * * XXX you don't really want to know about this: setrefs.c will apply * replace_vars_with_subplan_refs() to the Result node's tlist. - * This would fail if the input plan's non-resjunk tlist entries were - * not all simple Vars equal() to the referencing Vars generated by - * generate_setop_tlist(). However, since the input plan was - * generated by generate_union_plan() or generate_nonunion_plan(), - * the referencing Vars will equal the tlist entries they reference. - * Ugly but I don't feel like making that code more general right now. + * This would fail if the input plan's non-resjunk tlist entries + * were not all simple Vars equal() to the referencing Vars + * generated by generate_setop_tlist(). However, since the input + * plan was generated by generate_union_plan() or + * generate_nonunion_plan(), the referencing Vars will equal the + * tlist entries they reference. Ugly but I don't feel like making + * that code more general right now. */ if (flag >= 0 || - ! tlist_same_datatypes(plan->targetlist, colTypes, junkOK)) + !tlist_same_datatypes(plan->targetlist, colTypes, junkOK)) { plan = (Plan *) make_result(generate_setop_tlist(colTypes, flag, false, @@ -199,8 +203,8 @@ static Plan * generate_union_plan(SetOperationStmt *op, Query *parse, List *refnames_tlist) { - List *planlist; - Plan *plan; + List *planlist; + Plan *plan; /* * If any of my children are identical UNION nodes (same op, all-flag, @@ -212,27 +216,29 @@ generate_union_plan(SetOperationStmt *op, Query *parse, op, refnames_tlist), recurse_union_children(op->rarg, parse, op, refnames_tlist)); + /* * Append the child results together. * - * The tlist for an Append plan isn't important as far as the Append - * is concerned, but we must make it look real anyway for the benefit - * of the next plan level up. + * The tlist for an Append plan isn't important as far as the Append is + * concerned, but we must make it look real anyway for the benefit of + * the next plan level up. */ plan = (Plan *) make_append(planlist, false, generate_setop_tlist(op->colTypes, -1, false, - ((Plan *) lfirst(planlist))->targetlist, - refnames_tlist)); + ((Plan *) lfirst(planlist))->targetlist, + refnames_tlist)); + /* - * For UNION ALL, we just need the Append plan. For UNION, - * need to add Sort and Unique nodes to produce unique output. + * For UNION ALL, we just need the Append plan. For UNION, need to + * add Sort and Unique nodes to produce unique output. */ - if (! op->all) + if (!op->all) { - List *tlist, - *sortList; + List *tlist, + *sortList; tlist = new_unsorted_tlist(plan->targetlist); sortList = addAllTargetsToSortList(NIL, tlist); @@ -249,12 +255,12 @@ static Plan * generate_nonunion_plan(SetOperationStmt *op, Query *parse, List *refnames_tlist) { - Plan *lplan, - *rplan, - *plan; - List *tlist, - *sortList; - SetOpCmd cmd; + Plan *lplan, + *rplan, + *plan; + List *tlist, + *sortList; + SetOpCmd cmd; /* Recurse on children, ensuring their outputs are marked */ lplan = recurse_set_operations(op->larg, parse, @@ -263,12 +269,13 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, rplan = recurse_set_operations(op->rarg, parse, op->colTypes, false, 1, refnames_tlist); + /* * Append the child results together. * - * The tlist for an Append plan isn't important as far as the Append - * is concerned, but we must make it look real anyway for the benefit - * of the next plan level up. + * The tlist for an Append plan isn't important as far as the Append is + * concerned, but we must make it look real anyway for the benefit of + * the next plan level up. */ plan = (Plan *) make_append(makeList2(lplan, rplan), @@ -276,9 +283,10 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, generate_setop_tlist(op->colTypes, 0, false, lplan->targetlist, refnames_tlist)); + /* - * Sort the child results, then add a SetOp plan node to - * generate the correct output. + * Sort the child results, then add a SetOp plan node to generate the + * correct output. */ tlist = new_unsorted_tlist(plan->targetlist); sortList = addAllTargetsToSortList(NIL, tlist); @@ -293,11 +301,11 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, break; default: elog(ERROR, "generate_nonunion_plan: bogus operation code"); - cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */ + cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */ break; } plan = (Plan *) make_setop(cmd, tlist, plan, sortList, - length(op->colTypes)+1); + length(op->colTypes) + 1); return plan; } @@ -322,20 +330,21 @@ recurse_union_children(Node *setOp, Query *parse, { /* Same UNION, so fold children into parent's subplan list */ return nconc(recurse_union_children(op->larg, parse, - top_union, refnames_tlist), + top_union, refnames_tlist), recurse_union_children(op->rarg, parse, - top_union, refnames_tlist)); + top_union, refnames_tlist)); } } + /* * Not same, so plan this child separately. * - * Note we disallow any resjunk columns in child results. This - * is necessary since the Append node that implements the union - * won't do any projection, and upper levels will get confused if - * some of our output tuples have junk and some don't. This case - * only arises when we have an EXCEPT or INTERSECT as child, else - * there won't be resjunk anyway. + * Note we disallow any resjunk columns in child results. This is + * necessary since the Append node that implements the union won't do + * any projection, and upper levels will get confused if some of our + * output tuples have junk and some don't. This case only arises when + * we have an EXCEPT or INTERSECT as child, else there won't be + * resjunk anyway. */ return makeList1(recurse_set_operations(setOp, parse, top_union->colTypes, false, @@ -359,7 +368,7 @@ generate_setop_tlist(List *colTypes, int flag, foreach(i, colTypes) { - Oid colType = (Oid) lfirsti(i); + Oid colType = (Oid) lfirsti(i); TargetEntry *inputtle = (TargetEntry *) lfirst(input_tlist); TargetEntry *reftle = (TargetEntry *) lfirst(refnames_tlist); @@ -367,18 +376,19 @@ generate_setop_tlist(List *colTypes, int flag, Assert(reftle->resdom->resno == resno); Assert(!inputtle->resdom->resjunk); Assert(!reftle->resdom->resjunk); + /* * Generate columns referencing input columns and having * appropriate data types and column names. Insert datatype * coercions where necessary. * * HACK: constants in the input's targetlist are copied up as-is - * rather than being referenced as subquery outputs. This is mainly - * to ensure that when we try to coerce them to the output column's - * datatype, the right things happen for UNKNOWN constants. But do - * this only at the first level of subquery-scan plans; we don't - * want phony constants appearing in the output tlists of upper-level - * nodes! + * rather than being referenced as subquery outputs. This is + * mainly to ensure that when we try to coerce them to the output + * column's datatype, the right things happen for UNKNOWN + * constants. But do this only at the first level of + * subquery-scan plans; we don't want phony constants appearing in + * the output tlists of upper-level nodes! */ resdom = makeResdom((AttrNumber) resno++, colType, @@ -440,7 +450,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK) if (tle->resdom->resjunk) { - if (! junkOK) + if (!junkOK) return false; } else @@ -484,11 +494,11 @@ find_all_inheritors(Oid parentrel) currentchildren = find_inheritance_children(currentrel); /* - * Add to the queue only those children not already seen. - * This avoids making duplicate entries in case of multiple - * inheritance paths from the same parent. (It'll also keep - * us from getting into an infinite loop, though theoretically - * there can't be any cycles in the inheritance graph anyway.) + * Add to the queue only those children not already seen. This + * avoids making duplicate entries in case of multiple inheritance + * paths from the same parent. (It'll also keep us from getting + * into an infinite loop, though theoretically there can't be any + * cycles in the inheritance graph anyway.) */ currentchildren = set_differencei(currentchildren, examined_relids); unexamined_relids = set_unioni(unexamined_relids, currentchildren); @@ -524,20 +534,21 @@ expand_inherted_rtentry(Query *parse, Index rti) List *l; /* Does RT entry allow inheritance? */ - if (! rte->inh) + if (!rte->inh) return NIL; Assert(parentOID != InvalidOid && rte->subquery == NULL); /* Always clear the parent's inh flag, see above comments */ rte->inh = false; /* Fast path for common case of childless table */ - if (! has_subclass(parentOID)) + if (!has_subclass(parentOID)) return NIL; /* Scan for all members of inheritance set */ inhOIDs = find_all_inheritors(parentOID); + /* - * Check that there's at least one descendant, else treat as - * no-child case. This could happen despite above has_subclass() - * check, if table once had a child but no longer does. + * Check that there's at least one descendant, else treat as no-child + * case. This could happen despite above has_subclass() check, if + * table once had a child but no longer does. */ if (lnext(inhOIDs) == NIL) return NIL; @@ -545,18 +556,19 @@ expand_inherted_rtentry(Query *parse, Index rti) inhRTIs = makeListi1(rti); foreach(l, inhOIDs) { - Oid childOID = (Oid) lfirsti(l); + Oid childOID = (Oid) lfirsti(l); RangeTblEntry *childrte; - Index childRTindex; + Index childRTindex; /* parent will be in the list too, so ignore it */ if (childOID == parentOID) continue; /* - * Build an RTE for the child, and attach to query's rangetable list. - * We copy most fields of the parent's RTE, but replace relation - * real name and OID. Note that inh will be false at this point. + * Build an RTE for the child, and attach to query's rangetable + * list. We copy most fields of the parent's RTE, but replace + * relation real name and OID. Note that inh will be false at + * this point. */ childrte = copyObject(rte); childrte->relname = get_rel_name(childOID); @@ -575,12 +587,12 @@ expand_inherted_rtentry(Query *parse, Index rti) * to old_rt_index to refer to new_rt_index. * * We also adjust varattno to match the new table by column name, rather - * than column number. This hack makes it possible for child tables to have + * than column number. This hack makes it possible for child tables to have * different column positions for the "same" attribute as a parent, which * helps ALTER TABLE ADD COLUMN. Unfortunately this isn't nearly enough to * make it work transparently; there are other places where things fall down * if children and parents don't have the same column numbers for inherited - * attributes. It'd be better to rip this code out and fix ALTER TABLE... + * attributes. It'd be better to rip this code out and fix ALTER TABLE... */ Node * adjust_inherited_attrs(Node *node, @@ -643,12 +655,13 @@ adjust_inherited_attrs_mutator(Node *node, } if (IsA(node, RangeTblRef)) { - RangeTblRef *rtr = (RangeTblRef *) copyObject(node); + RangeTblRef *rtr = (RangeTblRef *) copyObject(node); if (rtr->rtindex == context->old_rt_index) rtr->rtindex = context->new_rt_index; return (Node *) rtr; } + /* * We have to process RestrictInfo nodes specially: we do NOT want to * copy the original subclauseindices list, since the new rel may have @@ -656,8 +669,8 @@ adjust_inherited_attrs_mutator(Node *node, */ if (IsA(node, RestrictInfo)) { - RestrictInfo *oldinfo = (RestrictInfo *) node; - RestrictInfo *newinfo = makeNode(RestrictInfo); + RestrictInfo *oldinfo = (RestrictInfo *) node; + RestrictInfo *newinfo = makeNode(RestrictInfo); /* Copy all flat-copiable fields */ memcpy(newinfo, oldinfo, sizeof(RestrictInfo)); @@ -666,18 +679,19 @@ adjust_inherited_attrs_mutator(Node *node, adjust_inherited_attrs_mutator((Node *) oldinfo->clause, context); newinfo->subclauseindices = NIL; - newinfo->eval_cost = -1; /* reset this too */ - newinfo->left_pathkey = NIL; /* and these */ + newinfo->eval_cost = -1;/* reset this too */ + newinfo->left_pathkey = NIL; /* and these */ newinfo->right_pathkey = NIL; newinfo->left_dispersion = -1; newinfo->right_dispersion = -1; return (Node *) newinfo; } + /* * NOTE: we do not need to recurse into sublinks, because they should * already have been converted to subplans before we see them. */ return expression_tree_mutator(node, adjust_inherited_attrs_mutator, - (void *) context); + (void *) context); } diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index bc05908148b..83d2468b02c 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.82 2001/03/08 01:49:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.83 2001/03/22 03:59:39 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -544,8 +544,8 @@ check_subplans_for_ungrouped_vars_walker(Node *node, /* * If we find an aggregate function, do not recurse into its - * arguments. Subplans invoked within aggregate calls are allowed - * to receive ungrouped variables. + * arguments. Subplans invoked within aggregate calls are allowed to + * receive ungrouped variables. */ if (IsA(node, Aggref)) return false; @@ -630,7 +630,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node, * Recursively search for noncachable functions within a clause. * * Returns true if any noncachable function (or operator implemented by a - * noncachable function) is found. This test is needed so that we don't + * noncachable function) is found. This test is needed so that we don't * mistakenly think that something like "WHERE random() < 0.5" can be treated * as a constant qualification. * @@ -655,11 +655,11 @@ contain_noncachable_functions_walker(Node *node, void *context) switch (expr->opType) { case OP_EXPR: - if (! op_iscachable(((Oper *) expr->oper)->opno)) + if (!op_iscachable(((Oper *) expr->oper)->opno)) return true; break; case FUNC_EXPR: - if (! func_iscachable(((Func *) expr->oper)->funcid)) + if (!func_iscachable(((Func *) expr->oper)->funcid)) return true; break; default: @@ -680,13 +680,14 @@ contain_noncachable_functions_walker(Node *node, void *context) * Detect whether a clause is "constant", ie, it contains no variables * of the current query level and no uses of noncachable functions. * Such a clause is not necessarily a true constant: it can still contain - * Params and outer-level Vars. However, its value will be constant over + * Params and outer-level Vars. However, its value will be constant over * any one scan of the current query, so it can be used as an indexscan * key or (if a top-level qual) can be pushed up to become a gating qual. */ bool is_pseudo_constant_clause(Node *clause) { + /* * We could implement this check in one recursive scan. But since the * check for noncachable functions is both moderately expensive and @@ -716,7 +717,7 @@ pull_constant_clauses(List *quals, List **constantQual) foreach(q, quals) { - Node *qual = (Node *) lfirst(q); + Node *qual = (Node *) lfirst(q); if (is_pseudo_constant_clause(qual)) constqual = lappend(constqual, qual); @@ -1277,8 +1278,8 @@ eval_const_expressions_mutator(Node *node, void *context) arg = eval_const_expressions_mutator(relabel->arg, context); /* - * If we find stacked RelabelTypes (eg, from foo :: int :: oid) - * we can discard all but the top one. + * If we find stacked RelabelTypes (eg, from foo :: int :: oid) we + * can discard all but the top one. */ while (arg && IsA(arg, RelabelType)) arg = ((RelabelType *) arg)->arg; @@ -1472,8 +1473,8 @@ simplify_op_or_func(Expr *expr, List *args) * If the function is strict and has a constant-NULL input, it will * never be called at all, so we can replace the call by a NULL * constant even if there are other inputs that aren't constant. - * Otherwise, we can only simplify if all inputs are constants. - * We can skip the function lookup if neither case applies. + * Otherwise, we can only simplify if all inputs are constants. We can + * skip the function lookup if neither case applies. */ if (has_nonconst_input && !has_null_input) return NULL; @@ -1500,9 +1501,10 @@ simplify_op_or_func(Expr *expr, List *args) funcid = func->funcid; result_typeid = func->functype; } + /* - * we could use func_iscachable() here, but we need several fields - * out of the func tuple, so might as well just look it up once. + * we could use func_iscachable() here, but we need several fields out + * of the func tuple, so might as well just look it up once. */ func_tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), @@ -1530,6 +1532,7 @@ simplify_op_or_func(Expr *expr, List *args) */ if (proisstrict && has_null_input) { + /* * It's strict and has NULL input, so must produce NULL output. * Return a NULL constant of the right type. @@ -1538,9 +1541,9 @@ simplify_op_or_func(Expr *expr, List *args) } /* - * Otherwise, can simplify only if all inputs are constants. - * (For a non-strict function, constant NULL inputs are treated - * the same as constant non-NULL inputs.) + * Otherwise, can simplify only if all inputs are constants. (For a + * non-strict function, constant NULL inputs are treated the same as + * constant non-NULL inputs.) */ if (has_nonconst_input) return NULL; @@ -1565,10 +1568,10 @@ simplify_op_or_func(Expr *expr, List *args) get_typlenbyval(result_typeid, &resultTypLen, &resultTypByVal); /* - * It is OK to pass a dummy econtext because none of the ExecEvalExpr() - * code used in this situation will use econtext. That might seem - * fortuitous, but it's not so unreasonable --- a constant expression - * does not depend on context, by definition, n'est ce pas? + * It is OK to pass a dummy econtext because none of the + * ExecEvalExpr() code used in this situation will use econtext. That + * might seem fortuitous, but it's not so unreasonable --- a constant + * expression does not depend on context, by definition, n'est ce pas? */ econtext = MakeExprContext(NULL, CurrentMemoryContext); @@ -1657,10 +1660,10 @@ simplify_op_or_func(Expr *expr, List *args) * expression_tree_walker itself is called on a Query node, it does nothing * and returns "false". The net effect is that unless the walker does * something special at a Query node, sub-selects will not be visited - * during an expression tree walk. This is exactly the behavior wanted + * during an expression tree walk. This is exactly the behavior wanted * in many cases --- and for those walkers that do want to recurse into * sub-selects, special behavior is typically needed anyway at the entry - * to a sub-select (such as incrementing a depth counter). A walker that + * to a sub-select (such as incrementing a depth counter). A walker that * wants to examine sub-selects should include code along the lines of: * * if (IsA(node, Query)) @@ -1780,9 +1783,10 @@ expression_tree_walker(Node *node, /* * If the SubLink has already been processed by * subselect.c, it will have lefthand=NIL, and we need to - * scan the oper list. Otherwise we only need to look at - * the lefthand list (the incomplete Oper nodes in the oper - * list are deemed uninteresting, perhaps even confusing). + * scan the oper list. Otherwise we only need to look at + * the lefthand list (the incomplete Oper nodes in the + * oper list are deemed uninteresting, perhaps even + * confusing). */ if (sublink->lefthand) { @@ -1794,9 +1798,10 @@ expression_tree_walker(Node *node, if (walker((Node *) sublink->oper, context)) return true; } + /* - * Also invoke the walker on the sublink's Query node, - * so it can recurse into the sub-query if it wants to. + * Also invoke the walker on the sublink's Query node, so + * it can recurse into the sub-query if it wants to. */ return walker(sublink->subselect, context); } @@ -1815,7 +1820,7 @@ expression_tree_walker(Node *node, return walker(((TargetEntry *) node)->expr, context); case T_FromExpr: { - FromExpr *from = (FromExpr *) node; + FromExpr *from = (FromExpr *) node; if (walker(from->fromlist, context)) return true; @@ -1825,7 +1830,7 @@ expression_tree_walker(Node *node, break; case T_JoinExpr: { - JoinExpr *join = (JoinExpr *) node; + JoinExpr *join = (JoinExpr *) node; if (walker(join->larg, context)) return true; @@ -1835,7 +1840,9 @@ expression_tree_walker(Node *node, return true; if (walker((Node *) join->colvars, context)) return true; - /* alias clause, using list, colnames list are deemed + + /* + * alias clause, using list, colnames list are deemed * uninteresting. */ } @@ -1890,7 +1897,7 @@ query_tree_walker(Query *query, return true; if (visitQueryRTEs) { - List *rt; + List *rt; foreach(rt, query->rtable) { @@ -2176,8 +2183,8 @@ expression_tree_mutator(Node *node, break; case T_FromExpr: { - FromExpr *from = (FromExpr *) node; - FromExpr *newnode; + FromExpr *from = (FromExpr *) node; + FromExpr *newnode; FLATCOPY(newnode, from, FromExpr); MUTATE(newnode->fromlist, from->fromlist, List *); @@ -2187,8 +2194,8 @@ expression_tree_mutator(Node *node, break; case T_JoinExpr: { - JoinExpr *join = (JoinExpr *) node; - JoinExpr *newnode; + JoinExpr *join = (JoinExpr *) node; + JoinExpr *newnode; FLATCOPY(newnode, join, JoinExpr); MUTATE(newnode->larg, join->larg, Node *); @@ -2226,7 +2233,7 @@ expression_tree_mutator(Node *node, * This routine exists just to reduce the number of places that need to know * where all the expression subtrees of a Query are. Note it can be used * for starting a walk at top level of a Query regardless of whether the - * mutator intends to descend into subqueries. It is also useful for + * mutator intends to descend into subqueries. It is also useful for * descending into subqueries within a mutator. * * The specified Query node is modified-in-place; do a FLATCOPY() beforehand @@ -2252,8 +2259,8 @@ query_tree_mutator(Query *query, MUTATE(query->havingQual, query->havingQual, Node *); if (visitQueryRTEs) { - List *newrt = NIL; - List *rt; + List *newrt = NIL; + List *rt; foreach(rt, query->rtable) { diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c index 81bb3bb9e88..ec98dbcb24f 100644 --- a/src/backend/optimizer/util/joininfo.c +++ b/src/backend/optimizer/util/joininfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.28 2001/01/24 19:43:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.29 2001/03/22 03:59:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,7 +33,7 @@ static JoinInfo *joininfo_member(List *join_relids, List *joininfo_list); * exists. * */ -static JoinInfo * +static JoinInfo * joininfo_member(List *join_relids, List *joininfo_list) { List *i; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 1a0dfc67df7..cfba3ee395f 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.70 2001/01/24 19:43:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.71 2001/03/22 03:59:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -192,7 +192,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * possible for more than one old path to be tossed out because * new_path dominates it. */ - p1 = parent_rel->pathlist; /* cannot use foreach here */ + p1 = parent_rel->pathlist; /* cannot use foreach here */ while (p1 != NIL) { Path *old_path = (Path *) lfirst(p1); @@ -243,7 +243,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path) */ if (remove_old && parent_rel->pruneable) { - List *p1_next = lnext(p1); + List *p1_next = lnext(p1); if (p1_prev) lnext(p1_prev) = p1_next; @@ -409,14 +409,15 @@ create_append_path(RelOptInfo *rel, List *subpaths) pathnode->path.pathtype = T_Append; pathnode->path.parent = rel; - pathnode->path.pathkeys = NIL; /* result is always considered unsorted */ + pathnode->path.pathkeys = NIL; /* result is always considered + * unsorted */ pathnode->subpaths = subpaths; pathnode->path.startup_cost = 0; pathnode->path.total_cost = 0; foreach(l, subpaths) { - Path *subpath = (Path *) lfirst(l); + Path *subpath = (Path *) lfirst(l); if (l == subpaths) /* first node? */ pathnode->path.startup_cost = subpath->startup_cost; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index e4c3a077a30..4f711df203c 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.63 2001/01/24 19:43:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.64 2001/03/22 03:59:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -83,8 +83,8 @@ find_secondary_indexes(Oid relationObjectId) Relation relation; /* - * We used to scan pg_index directly, but now the relcache offers - * a cached list of OID indexes for each relation. So, get that list + * We used to scan pg_index directly, but now the relcache offers a + * cached list of OID indexes for each relation. So, get that list * and then use the syscache to obtain pg_index entries. */ relation = heap_open(relationObjectId, AccessShareLock); @@ -126,7 +126,7 @@ find_secondary_indexes(Oid relationObjectId) char *predString; predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&index->indpred))); + PointerGetDatum(&index->indpred))); info->indpred = (List *) stringToNode(predString); pfree(predString); } @@ -213,11 +213,11 @@ restriction_selectivity(Oid functionObjectId, float8 result; result = DatumGetFloat8(OidFunctionCall5(functionObjectId, - ObjectIdGetDatum(operatorObjectId), - ObjectIdGetDatum(relationObjectId), - Int16GetDatum(attributeNumber), - constValue, - Int32GetDatum(constFlag))); + ObjectIdGetDatum(operatorObjectId), + ObjectIdGetDatum(relationObjectId), + Int16GetDatum(attributeNumber), + constValue, + Int32GetDatum(constFlag))); if (result < 0.0 || result > 1.0) elog(ERROR, "restriction_selectivity: bad value %f", result); @@ -246,11 +246,11 @@ join_selectivity(Oid functionObjectId, float8 result; result = DatumGetFloat8(OidFunctionCall5(functionObjectId, - ObjectIdGetDatum(operatorObjectId), - ObjectIdGetDatum(relationObjectId1), - Int16GetDatum(attributeNumber1), - ObjectIdGetDatum(relationObjectId2), - Int16GetDatum(attributeNumber2))); + ObjectIdGetDatum(operatorObjectId), + ObjectIdGetDatum(relationObjectId1), + Int16GetDatum(attributeNumber1), + ObjectIdGetDatum(relationObjectId2), + Int16GetDatum(attributeNumber2))); if (result < 0.0 || result > 1.0) elog(ERROR, "join_selectivity: bad value %f", result); @@ -277,13 +277,13 @@ find_inheritance_children(Oid inhparent) HeapScanDesc scan; HeapTuple inheritsTuple; Oid inhrelid; - ScanKeyData key[1]; + ScanKeyData key[1]; /* - * Can skip the scan if pg_class shows the relation has never had - * a subclass. + * Can skip the scan if pg_class shows the relation has never had a + * subclass. */ - if (! has_subclass(inhparent)) + if (!has_subclass(inhparent)) return NIL; ScanKeyEntryInitialize(&key[0], @@ -306,7 +306,7 @@ find_inheritance_children(Oid inhparent) /* * has_subclass * - * In the current implementation, has_subclass returns whether a + * In the current implementation, has_subclass returns whether a * particular class *might* have a subclass. It will not return the * correct result if a class had a subclass which was later dropped. * This is because relhassubclass in pg_class is not updated when a diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index b9296fdfa00..9d5d6c080e7 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.49 2001/01/24 19:43:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.50 2001/03/22 03:59:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -60,6 +60,7 @@ matching_tlist_expr(Node *node, List *targetlist) return (Node *) NULL; } + #endif /* diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 1347bd9a522..cac0eee8276 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.29 2001/01/24 19:43:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.30 2001/03/22 03:59:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,7 @@ typedef struct } pull_var_clause_context; static bool pull_varnos_walker(Node *node, - pull_varnos_context *context); + pull_varnos_context *context); static bool contain_var_clause_walker(Node *node, void *context); static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context); @@ -90,15 +90,16 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) } if (is_subplan(node)) { + /* - * Already-planned subquery. Examine the args list (parameters - * to be passed to subquery), as well as the "oper" list which - * is executed by the outer query. But short-circuit recursion into + * Already-planned subquery. Examine the args list (parameters to + * be passed to subquery), as well as the "oper" list which is + * executed by the outer query. But short-circuit recursion into * the subquery itself, which would be a waste of effort. */ Expr *expr = (Expr *) node; - if (pull_varnos_walker((Node*) ((SubPlan*) expr->oper)->sublink->oper, + if (pull_varnos_walker((Node *) ((SubPlan *) expr->oper)->sublink->oper, context)) return true; if (pull_varnos_walker((Node *) expr->args, |