diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README index 2b6ff52c5ff0141bad2b00a634a9fee6c4e7a980..b25d7fb5f1aa9dd1620dab19a45b49c58687913f 100644 --- a/src/backend/optimizer/README +++ b/src/backend/optimizer/README @@ -7,7 +7,9 @@ The optimizer generates optimial query plans by doing several steps: it. Find each way of accessing the relation, called a Path, including sequential and index scans, and add it to RelOptInfo.pathlist. Also create RelOptInfo.joininfo that lists all the joins that involve this -relation. +relation. For example, the WHERE clause "tab1.col1 = tab2.col1" +generates a JoinInfo for tab1 listing tab2 as an unjoined relation, and +tab2's joininfo shows tab1 as an unjoined relation. 2) Join each RelOptInfo to other RelOptInfo as specified in RelOptInfo.joininfo. At this point each RelOptInfo is a single diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 4846dfba50f203687f9c19dde79e175e6b82b332..6a1bad07b70f9ec5d36d818c4bf85cc65aa6cb9f 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.29 1999/02/18 19:58:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.30 1999/02/19 05:18:04 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -79,8 +79,8 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels) List *pathlist = NIL; /* flatten out relids later in this function */ - innerrelids = lsecond(joinrel->relids); outerrelids = lfirst(joinrel->relids); + innerrelids = lsecond(joinrel->relids); /* * base relation id is an integer and join relation relid is a @@ -123,7 +123,7 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels) outerrel, innerrel, outerrel->pathlist, - (Path *) innerrel->cheapestpath, + innerrel->cheapestpath, bestinnerjoin, mergeinfo_list)); @@ -176,7 +176,6 @@ best_innerjoin(List *join_paths, Relids outer_relids) && ((cheapest == NULL || path_is_cheaper((Path *) lfirst(join_path), cheapest)))) { - cheapest = (Path *) lfirst(join_path); } } @@ -293,7 +292,7 @@ match_unsorted_outer(RelOptInfo *joinrel, List *clauses = NIL; List *matchedJoinKeys = NIL; List *matchedJoinClauses = NIL; - MergeInfo *xmergeinfo = (MergeInfo *) NULL; + MergeInfo *xmergeinfo = NULL; outerpath = (Path *) lfirst(i); @@ -309,9 +308,8 @@ match_unsorted_outer(RelOptInfo *joinrel, if (clauses) { List *jmkeys = xmergeinfo->jmethod.jmkeys; - List *clauses = xmergeinfo->jmethod.clauses; - matchedJoinKeys = match_pathkeys_joinkeys(outerpath->pathkeys, + matchedJoinKeys = order_joinkeys_by_pathkeys(outerpath->pathkeys, jmkeys, clauses, OUTER, @@ -339,19 +337,18 @@ match_unsorted_outer(RelOptInfo *joinrel, { bool path_is_cheaper_than_sort; List *varkeys = NIL; - Path *mergeinnerpath = match_paths_joinkeys(matchedJoinKeys, - outerpath_ordering, - innerrel->pathlist, - INNER); + Path *mergeinnerpath = get_cheapest_path_for_joinkeys( + matchedJoinKeys, + outerpath_ordering, + innerrel->pathlist, + INNER); /* Should we use the mergeinner, or sort the cheapest inner? */ path_is_cheaper_than_sort = (bool) (mergeinnerpath && - (mergeinnerpath->path_cost < - (cheapest_inner->path_cost + - cost_sort(matchedJoinKeys, - innerrel->size, - innerrel->width, - false)))); + (mergeinnerpath->path_cost < + (cheapest_inner->path_cost + + cost_sort(matchedJoinKeys, innerrel->size, + innerrel->width, false)))); if (!path_is_cheaper_than_sort) { varkeys = extract_path_keys(matchedJoinKeys, @@ -451,11 +448,10 @@ match_unsorted_inner(RelOptInfo *joinrel, if (clauses) { List *jmkeys = xmergeinfo->jmethod.jmkeys; - List *cls = xmergeinfo->jmethod.clauses; - matchedJoinKeys = match_pathkeys_joinkeys(innerpath->pathkeys, + matchedJoinKeys = order_joinkeys_by_pathkeys(innerpath->pathkeys, jmkeys, - cls, + clauses, INNER, &matchedJoinClauses); } diff --git a/src/backend/optimizer/path/pathkey.c b/src/backend/optimizer/path/pathkey.c index 92b27a774b22ad7fa455eaa33290d0a3d2eb9864..7d098db8850e6a80458cd78bdf0c8e715e8f2d1c 100644 --- a/src/backend/optimizer/path/pathkey.c +++ b/src/backend/optimizer/path/pathkey.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/pathkey.c,v 1.2 1999/02/19 02:05:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/pathkey.c,v 1.3 1999/02/19 05:18:05 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,7 @@ static int match_pathkey_joinkeys(List *pathkey, List *joinkeys, int outer_or_inner); -static bool every_func(List *joinkeys, List *pathkey, +static bool joinkeys_pathkeys_match(List *joinkeys, List *pathkey, int outer_or_inner); static List *new_join_pathkey(List *subkeys, List *considered_subkeys, List *join_rel_tlist, List *joinclauses); @@ -40,7 +40,7 @@ static List *new_matching_subkeys(Var *subkey, List *considered_subkeys, ****************************************************************************/ /* - * match_pathkeys_joinkeys + * order_joinkeys_by_pathkeys * Attempts to match the keys of a path against the keys of join clauses. * This is done by looking for a matching join key in 'joinkeys' for * every path key in the list 'path.keys'. If there is a matching join key @@ -69,7 +69,7 @@ static List *new_matching_subkeys(Var *subkey, List *considered_subkeys, * in matchedJoinClausesPtr. - ay 11/94 */ List * -match_pathkeys_joinkeys(List *pathkeys, +order_joinkeys_by_pathkeys(List *pathkeys, List *joinkeys, List *joinclauses, int outer_or_inner, @@ -92,21 +92,18 @@ match_pathkeys_joinkeys(List *pathkeys, List *xjoinkey = nth(matched_joinkey_index, joinkeys); List *joinclause = nth(matched_joinkey_index, joinclauses); - matched_joinkeys = lcons(xjoinkey, matched_joinkeys); - matched_joinclauses = lcons(joinclause, matched_joinclauses); - - joinkeys = LispRemove(xjoinkey, joinkeys); + matched_joinkeys = lappend(matched_joinkeys, xjoinkey); + matched_joinclauses = lappend(matched_joinclauses, joinclause); } else + { + *matchedJoinClausesPtr = NIL; return NIL; - + } } - if (matched_joinkeys == NULL || - length(matched_joinkeys) != length(pathkeys)) - return NIL; - *matchedJoinClausesPtr = nreverse(matched_joinclauses); - return nreverse(matched_joinkeys); + *matchedJoinClausesPtr = matched_joinclauses; + return matched_joinkeys; } @@ -144,7 +141,7 @@ match_pathkey_joinkeys(List *pathkey, /* - * match_paths_joinkeys + * get_cheapest_path_for_joinkeys * Attempts to find a path in 'paths' whose keys match a set of join * keys 'joinkeys'. To match, * 1. the path node ordering must equal 'ordering'. @@ -165,31 +162,27 @@ match_pathkey_joinkeys(List *pathkey, * Find the cheapest path that matches the join keys */ Path * -match_paths_joinkeys(List *joinkeys, - PathOrder *ordering, - List *paths, - int outer_or_inner) +get_cheapest_path_for_joinkeys(List *joinkeys, + PathOrder *ordering, + List *paths, + int outer_or_inner) { Path *matched_path = NULL; - bool key_match = false; List *i = NIL; foreach(i, paths) { Path *path = (Path *) lfirst(i); - int better_sort; + int better_sort, better_key; - key_match = every_func(joinkeys, path->pathkeys, outer_or_inner); - - if (pathorder_match(ordering, path->pathorder, &better_sort) && - better_sort == 0 && - length(joinkeys) == length(path->pathkeys) && key_match) + if (joinkeys_pathkeys_match(joinkeys, path->pathkeys, outer_or_inner) && + length(joinkeys) == length(path->pathkeys) && + pathorder_match(ordering, path->pathorder, &better_sort) && + better_sort == 0) { if (matched_path) - { if (path->path_cost < matched_path->path_cost) matched_path = path; - } else matched_path = path; } @@ -253,10 +246,10 @@ extract_path_keys(List *joinkeys, /* - * every_func + * joinkeys_pathkeys_match */ static bool -every_func(List *joinkeys, List *pathkey, int outer_or_inner) +joinkeys_pathkeys_match(List *joinkeys, List *pathkey, int outer_or_inner) { JoinKey *xjoinkey; Var *temp; diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 413d536807c95281ca4cba74a8f6630b5ed7b6a8..f504fc790299409e3a6c39d4d1ee3be1ac5fddad 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: paths.h,v 1.23 1999/02/19 02:05:20 momjian Exp $ + * $Id: paths.h,v 1.24 1999/02/19 05:18:06 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -54,13 +54,13 @@ extern List *group_clauses_by_hashop(List *restrictinfo_list, * joinutils.h * generic join method key/clause routines */ -extern List *match_pathkeys_joinkeys(List *pathkeys, +extern List *order_joinkeys_by_pathkeys(List *pathkeys, List *joinkeys, List *joinclauses, int outer_or_inner, List **matchedJoinClausesPtr); extern List *extract_path_keys(List *joinkeys, List *tlist, int outer_or_inner); -extern Path *match_paths_joinkeys(List *joinkeys, PathOrder *ordering, - List *paths, int outer_or_inner); +extern Path *get_cheapest_path_for_joinkeys(List *joinkeys, + PathOrder *ordering, List *paths, int outer_or_inner); extern List *new_join_pathkeys(List *outer_pathkeys, List *join_rel_tlist, List *joinclauses);