1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* paths.h
|
2005-06-06 00:32:58 +02:00
|
|
|
* prototypes for various files in optimizer/path
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
2015-01-06 17:43:47 +01:00
|
|
|
* Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/include/optimizer/paths.h
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#ifndef PATHS_H
|
|
|
|
#define PATHS_H
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-11-26 02:14:33 +01:00
|
|
|
#include "nodes/relation.h"
|
|
|
|
|
2003-01-24 04:58:44 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-07-27 08:23:12 +02:00
|
|
|
* allpaths.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-01-23 00:50:30 +01:00
|
|
|
extern bool enable_geqo;
|
2003-01-26 00:10:30 +01:00
|
|
|
extern int geqo_threshold;
|
2014-11-21 20:05:46 +01:00
|
|
|
|
|
|
|
/* Hook for plugins to get control in set_rel_pathlist() */
|
|
|
|
typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
|
|
|
|
RelOptInfo *rel,
|
|
|
|
Index rti,
|
|
|
|
RangeTblEntry *rte);
|
|
|
|
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
|
2000-01-23 00:50:30 +01:00
|
|
|
|
2007-09-26 20:51:51 +02:00
|
|
|
/* Hook for plugins to replace standard_join_search() */
|
2007-11-15 22:14:46 +01:00
|
|
|
typedef RelOptInfo *(*join_search_hook_type) (PlannerInfo *root,
|
|
|
|
int levels_needed,
|
|
|
|
List *initial_rels);
|
2007-09-26 20:51:51 +02:00
|
|
|
extern PGDLLIMPORT join_search_hook_type join_search_hook;
|
|
|
|
|
|
|
|
|
2005-12-20 03:30:36 +01:00
|
|
|
extern RelOptInfo *make_one_rel(PlannerInfo *root, List *joinlist);
|
2007-09-26 20:51:51 +02:00
|
|
|
extern RelOptInfo *standard_join_search(PlannerInfo *root, int levels_needed,
|
2007-11-15 22:14:46 +01:00
|
|
|
List *initial_rels);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-10-18 18:11:42 +02:00
|
|
|
#ifdef OPTIMIZER_DEBUG
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
|
2001-10-18 18:11:42 +02:00
|
|
|
#endif
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-07-27 08:23:12 +02:00
|
|
|
* indxpath.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* routines to generate index paths
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
|
2009-09-17 22:49:29 +02:00
|
|
|
extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
|
2011-10-26 23:52:02 +02:00
|
|
|
List *restrictlist,
|
|
|
|
List *exprlist, List *oprlist);
|
2005-04-12 01:06:57 +02:00
|
|
|
extern bool match_index_to_operand(Node *operand, int indexcol,
|
|
|
|
IndexOptInfo *index);
|
2011-12-25 01:03:21 +01:00
|
|
|
extern void expand_indexqual_conditions(IndexOptInfo *index,
|
|
|
|
List *indexclauses, List *indexclausecols,
|
|
|
|
List **indexquals_p, List **indexqualcols_p);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void check_partial_indexes(PlannerInfo *root, RelOptInfo *rel);
|
Improve planner's handling of duplicated index column expressions.
It's potentially useful for an index to repeat the same indexable column
or expression in multiple index columns, if the columns have different
opclasses. (If they share opclasses too, the duplicate column is pretty
useless, but nonetheless we've allowed such cases since 9.0.) However,
the planner failed to cope with this, because createplan.c was relying on
simple equal() matching to figure out which index column each index qual
is intended for. We do have that information available upstream in
indxpath.c, though, so the fix is to not flatten the multi-level indexquals
list when putting it into an IndexPath. Then we can rely on the sublist
structure to identify target index columns in createplan.c. There's a
similar issue for index ORDER BYs (the KNNGIST feature), so introduce a
multi-level-list representation for that too. This adds a bit more
representational overhead, but we might more or less buy that back by not
having to search for matching index columns anymore in createplan.c;
likewise btcostestimate saves some cycles.
Per bug #6351 from Christian Rudolph. Likely symptoms include the "btree
index keys must be ordered by attribute" failure shown there, as well as
"operator MMMM is not a member of opfamily NNNN".
Although this is a pre-existing problem that can be demonstrated in 9.0 and
9.1, I'm not going to back-patch it, because the API changes in the planner
seem likely to break things such as index plugins. The corner cases where
this matters seem too narrow to justify possibly breaking things in a minor
release.
2011-12-24 00:44:21 +01:00
|
|
|
extern Expr *adjust_rowcompare_for_index(RowCompareExpr *clause,
|
|
|
|
IndexOptInfo *index,
|
|
|
|
int indexcol,
|
|
|
|
List **indexcolnos,
|
|
|
|
bool *var_on_left_p);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-11-23 21:07:06 +01:00
|
|
|
/*
|
|
|
|
* tidpath.h
|
|
|
|
* routines to generate tid paths
|
|
|
|
*/
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel);
|
1999-11-23 21:07:06 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-07-27 08:23:12 +02:00
|
|
|
* joinpath.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* routines to create join paths
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
|
2008-08-14 20:48:00 +02:00
|
|
|
RelOptInfo *outerrel, RelOptInfo *innerrel,
|
|
|
|
JoinType jointype, SpecialJoinInfo *sjinfo,
|
2001-03-22 05:01:46 +01:00
|
|
|
List *restrictlist);
|
2000-02-07 05:41:04 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* joinrels.c
|
|
|
|
* routines to determine which relations to join
|
|
|
|
*/
|
2009-11-28 01:46:19 +01:00
|
|
|
extern void join_search_one_level(PlannerInfo *root, int level);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern RelOptInfo *make_join_rel(PlannerInfo *root,
|
2005-12-20 03:30:36 +01:00
|
|
|
RelOptInfo *rel1, RelOptInfo *rel2);
|
Restructure code that is responsible for ensuring that clauseless joins are
considered when it is necessary to do so because of a join-order restriction
(that is, an outer-join or IN-subselect construct). The former coding was a
bit ad-hoc and inconsistent, and it missed some cases, as exposed by Mario
Weilguni's recent bug report. His specific problem was that an IN could be
turned into a "clauseless" join due to constant-propagation removing the IN's
joinclause, and if the IN's subselect involved more than one relation and
there was more than one such IN linking to the same upper relation, then the
only valid join orders involve "bushy" plans but we would fail to consider the
specific paths needed to get there. (See the example case added to the join
regression test.) On examining the code I wonder if there weren't some other
problem cases too; in particular it seems that GEQO was defending against a
different set of corner cases than the main planner was. There was also an
efficiency problem, in that when we did realize we needed a clauseless join
because of an IN, we'd consider clauseless joins against every other relation
whether this was sensible or not. It seems a better design is to use the
outer-join and in-clause lists as a backup heuristic, just as the rule of
joining only where there are joinclauses is a heuristic: we'll join two
relations if they have a usable joinclause *or* this might be necessary to
satisfy an outer-join or IN-clause join order restriction. I refactored the
code to have just one place considering this instead of three, and made sure
that it covered all the cases that any of them had been considering.
Backpatch as far as 8.1 (which has only the IN-clause form of the disease).
By rights 8.0 and 7.4 should have the bug too, but they accidentally fail
to fail, because the joininfo structure used in those releases preserves some
memory of there having once been a joinclause between the inner and outer
sides of an IN, and so it leads the code in the right direction anyway.
I'll be conservative and not touch them.
2007-02-16 01:14:01 +01:00
|
|
|
extern bool have_join_order_restriction(PlannerInfo *root,
|
|
|
|
RelOptInfo *rel1, RelOptInfo *rel2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
/*
|
|
|
|
* equivclass.c
|
|
|
|
* routines for managing EquivalenceClasses
|
|
|
|
*/
|
2013-03-22 00:43:59 +01:00
|
|
|
typedef bool (*ec_matches_callback_type) (PlannerInfo *root,
|
|
|
|
RelOptInfo *rel,
|
|
|
|
EquivalenceClass *ec,
|
|
|
|
EquivalenceMember *em,
|
|
|
|
void *arg);
|
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
extern bool process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
|
2007-11-15 22:14:46 +01:00
|
|
|
bool below_outer_join);
|
2011-03-20 01:29:08 +01:00
|
|
|
extern Expr *canonicalize_ec_expression(Expr *expr,
|
2011-04-10 17:42:00 +02:00
|
|
|
Oid req_type, Oid req_collation);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern void reconsider_outer_join_clauses(PlannerInfo *root);
|
|
|
|
extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root,
|
|
|
|
Expr *expr,
|
Compute correct em_nullable_relids in get_eclass_for_sort_expr().
Bug #8591 from Claudio Freire demonstrates that get_eclass_for_sort_expr
must be able to compute valid em_nullable_relids for any new equivalence
class members it creates. I'd worried about this in the commit message
for db9f0e1d9a4a0842c814a464cdc9758c3f20b96c, but claimed that it wasn't a
problem because multi-member ECs should already exist when it runs. That
is transparently wrong, though, because this function is also called by
initialize_mergeclause_eclasses, which runs during deconstruct_jointree.
The example given in the bug report (which the new regression test item
is based upon) fails because the COALESCE() expression is first seen by
initialize_mergeclause_eclasses rather than process_equivalence.
Fixing this requires passing the appropriate nullable_relids set to
get_eclass_for_sort_expr, and it requires new code to compute that set
for top-level expressions such as ORDER BY, GROUP BY, etc. We store
the top-level nullable_relids in a new field in PlannerInfo to avoid
computing it many times. In the back branches, I've added the new
field at the end of the struct to minimize ABI breakage for planner
plugins. There doesn't seem to be a good alternative to changing
get_eclass_for_sort_expr's API signature, though. There probably aren't
any third-party extensions calling that function directly; moreover,
if there are, they probably need to think about what to pass for
nullable_relids anyway.
Back-patch to 9.2, like the previous patch in this area.
2013-11-15 22:46:18 +01:00
|
|
|
Relids nullable_relids,
|
2007-11-08 22:49:48 +01:00
|
|
|
List *opfamilies,
|
2011-03-20 01:29:08 +01:00
|
|
|
Oid opcintype,
|
|
|
|
Oid collation,
|
2010-10-29 17:52:16 +02:00
|
|
|
Index sortref,
|
Revisit handling of UNION ALL subqueries with non-Var output columns.
In commit 57664ed25e5dea117158a2e663c29e60b3546e1c I tried to fix a bug
reported by Teodor Sigaev by making non-simple-Var output columns distinct
(by wrapping their expressions with dummy PlaceHolderVar nodes). This did
not work too well. Commit b28ffd0fcc583c1811e5295279e7d4366c3cae6c fixed
some ensuing problems with matching to child indexes, but per a recent
report from Claus Stadler, constraint exclusion of UNION ALL subqueries was
still broken, because constant-simplification didn't handle the injected
PlaceHolderVars well either. On reflection, the original patch was quite
misguided: there is no reason to expect that EquivalenceClass child members
will be distinct. So instead of trying to make them so, we should ensure
that we can cope with the situation when they're not.
Accordingly, this patch reverts the code changes in the above-mentioned
commits (though the regression test cases they added stay). Instead, I've
added assorted defenses to make sure that duplicate EC child members don't
cause any problems. Teodor's original problem ("MergeAppend child's
targetlist doesn't match MergeAppend") is addressed more directly by
revising prepare_sort_from_pathkeys to let the parent MergeAppend's sort
list guide creation of each child's sort list.
In passing, get rid of add_sort_column; as far as I can tell, testing for
duplicate sort keys at this stage is dead code. Certainly it doesn't
trigger often enough to be worth expending cycles on in ordinary queries.
And keeping the test would've greatly complicated the new logic in
prepare_sort_from_pathkeys, because comparing pathkey list entries against
a previous output array requires that we not skip any entries in the list.
Back-patch to 9.1, like the previous patches. The only known issue in
this area that wasn't caused by the ill-advised previous patches was the
MergeAppend planning failure, which of course is not relevant before 9.1.
It's possible that we need some of the new defenses against duplicate child
EC entries in older branches, but until there's some clear evidence of that
I'm going to refrain from back-patching further.
2012-03-16 18:11:12 +01:00
|
|
|
Relids rel,
|
2010-10-29 17:52:16 +02:00
|
|
|
bool create_it);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern void generate_base_implied_equalities(PlannerInfo *root);
|
|
|
|
extern List *generate_join_implied_equalities(PlannerInfo *root,
|
Revise parameterized-path mechanism to fix assorted issues.
This patch adjusts the treatment of parameterized paths so that all paths
with the same parameterization (same set of required outer rels) for the
same relation will have the same rowcount estimate. We cache the rowcount
estimates to ensure that property, and hopefully save a few cycles too.
Doing this makes it practical for add_path_precheck to operate without
a rowcount estimate: it need only assume that paths with different
parameterizations never dominate each other, which is close enough to
true anyway for coarse filtering, because normally a more-parameterized
path should yield fewer rows thanks to having more join clauses to apply.
In add_path, we do the full nine yards of comparing rowcount estimates
along with everything else, so that we can discard parameterized paths that
don't actually have an advantage. This fixes some issues I'd found with
add_path rejecting parameterized paths on the grounds that they were more
expensive than not-parameterized ones, even though they yielded many fewer
rows and hence would be cheaper once subsequent joining was considered.
To make the same-rowcounts assumption valid, we have to require that any
parameterized path enforce *all* join clauses that could be obtained from
the particular set of outer rels, even if not all of them are useful for
indexing. This is required at both base scans and joins. It's a good
thing anyway since the net impact is that join quals are checked at the
lowest practical level in the join tree. Hence, discard the original
rather ad-hoc mechanism for choosing parameterization joinquals, and build
a better one that has a more principled rule for when clauses can be moved.
The original rule was actually buggy anyway for lack of knowledge about
which relations are part of an outer join's outer side; getting this right
requires adding an outer_relids field to RestrictInfo.
2012-04-19 21:52:46 +02:00
|
|
|
Relids join_relids,
|
|
|
|
Relids outer_relids,
|
2007-11-15 22:14:46 +01:00
|
|
|
RelOptInfo *inner_rel);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2);
|
|
|
|
extern void add_child_rel_equivalences(PlannerInfo *root,
|
2007-11-15 22:14:46 +01:00
|
|
|
AppendRelInfo *appinfo,
|
|
|
|
RelOptInfo *parent_rel,
|
|
|
|
RelOptInfo *child_rel);
|
2008-03-31 18:59:26 +02:00
|
|
|
extern void mutate_eclass_expressions(PlannerInfo *root,
|
2009-06-11 16:49:15 +02:00
|
|
|
Node *(*mutator) (),
|
2012-11-26 18:57:17 +01:00
|
|
|
void *context,
|
|
|
|
bool include_child_exprs);
|
2013-03-22 00:43:59 +01:00
|
|
|
extern List *generate_implied_equalities_for_column(PlannerInfo *root,
|
|
|
|
RelOptInfo *rel,
|
|
|
|
ec_matches_callback_type callback,
|
|
|
|
void *callback_arg,
|
|
|
|
Relids prohibited_rels);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
|
|
|
|
RelOptInfo *rel1, RelOptInfo *rel2);
|
|
|
|
extern bool has_relevant_eclass_joinclause(PlannerInfo *root,
|
2007-11-15 22:14:46 +01:00
|
|
|
RelOptInfo *rel1);
|
2007-11-15 23:25:18 +01:00
|
|
|
extern bool eclass_useful_for_merging(EquivalenceClass *eclass,
|
2007-11-15 22:14:46 +01:00
|
|
|
RelOptInfo *rel);
|
Revise parameterized-path mechanism to fix assorted issues.
This patch adjusts the treatment of parameterized paths so that all paths
with the same parameterization (same set of required outer rels) for the
same relation will have the same rowcount estimate. We cache the rowcount
estimates to ensure that property, and hopefully save a few cycles too.
Doing this makes it practical for add_path_precheck to operate without
a rowcount estimate: it need only assume that paths with different
parameterizations never dominate each other, which is close enough to
true anyway for coarse filtering, because normally a more-parameterized
path should yield fewer rows thanks to having more join clauses to apply.
In add_path, we do the full nine yards of comparing rowcount estimates
along with everything else, so that we can discard parameterized paths that
don't actually have an advantage. This fixes some issues I'd found with
add_path rejecting parameterized paths on the grounds that they were more
expensive than not-parameterized ones, even though they yielded many fewer
rows and hence would be cheaper once subsequent joining was considered.
To make the same-rowcounts assumption valid, we have to require that any
parameterized path enforce *all* join clauses that could be obtained from
the particular set of outer rels, even if not all of them are useful for
indexing. This is required at both base scans and joins. It's a good
thing anyway since the net impact is that join quals are checked at the
lowest practical level in the join tree. Hence, discard the original
rather ad-hoc mechanism for choosing parameterization joinquals, and build
a better one that has a more principled rule for when clauses can be moved.
The original rule was actually buggy anyway for lack of knowledge about
which relations are part of an outer join's outer side; getting this right
requires adding an outer_relids field to RestrictInfo.
2012-04-19 21:52:46 +02:00
|
|
|
extern bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist);
|
2007-01-20 21:45:41 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-08-16 04:17:58 +02:00
|
|
|
* pathkeys.c
|
|
|
|
* utilities for matching and building path keys
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-08-16 04:17:58 +02:00
|
|
|
typedef enum
|
|
|
|
{
|
2001-10-28 07:26:15 +01:00
|
|
|
PATHKEYS_EQUAL, /* pathkeys are identical */
|
|
|
|
PATHKEYS_BETTER1, /* pathkey 1 is a superset of pathkey 2 */
|
|
|
|
PATHKEYS_BETTER2, /* vice versa */
|
|
|
|
PATHKEYS_DIFFERENT /* neither pathkey includes the other */
|
1999-08-16 04:17:58 +02:00
|
|
|
} PathKeysComparison;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-08-16 04:17:58 +02:00
|
|
|
extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
|
|
|
|
extern bool pathkeys_contained_in(List *keys1, List *keys2);
|
1999-08-21 05:49:17 +02:00
|
|
|
extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
2012-01-28 01:26:38 +01:00
|
|
|
Relids required_outer,
|
2000-04-12 19:17:23 +02:00
|
|
|
CostSelector cost_criterion);
|
2000-02-15 21:49:31 +01:00
|
|
|
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
2000-04-12 19:17:23 +02:00
|
|
|
List *pathkeys,
|
2012-01-28 01:26:38 +01:00
|
|
|
Relids required_outer,
|
2000-04-12 19:17:23 +02:00
|
|
|
double fraction);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
|
2007-01-20 21:45:41 +01:00
|
|
|
ScanDirection scandir);
|
Support multi-argument UNNEST(), and TABLE() syntax for multiple functions.
This patch adds the ability to write TABLE( function1(), function2(), ...)
as a single FROM-clause entry. The result is the concatenation of the
first row from each function, followed by the second row from each
function, etc; with NULLs inserted if any function produces fewer rows than
others. This is believed to be a much more useful behavior than what
Postgres currently does with multiple SRFs in a SELECT list.
This syntax also provides a reasonable way to combine use of column
definition lists with WITH ORDINALITY: put the column definition list
inside TABLE(), where it's clear that it doesn't control the ordinality
column as well.
Also implement SQL-compliant multiple-argument UNNEST(), by turning
UNNEST(a,b,c) into TABLE(unnest(a), unnest(b), unnest(c)).
The SQL standard specifies TABLE() with only a single function, not
multiple functions, and it seems to require an implicit UNNEST() which is
not what this patch does. There may be something wrong with that reading
of the spec, though, because if it's right then the spec's TABLE() is just
a pointless alternative spelling of UNNEST(). After further review of
that, we might choose to adopt a different syntax for what this patch does,
but in any case this functionality seems clearly worthwhile.
Andrew Gierth, reviewed by Zoltán Böszörményi and Heikki Linnakangas, and
significantly revised by me
2013-11-22 01:37:02 +01:00
|
|
|
extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,
|
|
|
|
Relids nullable_relids, Oid opno,
|
|
|
|
Relids rel, bool create_it);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern List *convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
2005-10-15 04:49:52 +02:00
|
|
|
List *subquery_pathkeys);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern List *build_join_pathkeys(PlannerInfo *root,
|
2001-03-22 05:01:46 +01:00
|
|
|
RelOptInfo *joinrel,
|
2005-01-23 03:21:36 +01:00
|
|
|
JoinType jointype,
|
2001-03-22 05:01:46 +01:00
|
|
|
List *outer_pathkeys);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern List *make_pathkeys_for_sortclauses(PlannerInfo *root,
|
|
|
|
List *sortclauses,
|
Postpone creation of pathkeys lists to fix bug #8049.
This patch gets rid of the concept of, and infrastructure for,
non-canonical PathKeys; we now only ever create canonical pathkey lists.
The need for non-canonical pathkeys came from the desire to have
grouping_planner initialize query_pathkeys and related pathkey lists before
calling query_planner. However, since query_planner didn't actually *do*
anything with those lists before they'd been made canonical, we can get rid
of the whole mess by just not creating the lists at all until the point
where we formerly canonicalized them.
There are several ways in which we could implement that without making
query_planner itself deal with grouping/sorting features (which are
supposed to be the province of grouping_planner). I chose to add a
callback function to query_planner's API; other alternatives would have
required adding more fields to PlannerInfo, which while not bad in itself
would create an ABI break for planner-related plugins in the 9.2 release
series. This still breaks ABI for anything that calls query_planner
directly, but it seems somewhat unlikely that there are any such plugins.
I had originally conceived of this change as merely a step on the way to
fixing bug #8049 from Teun Hoogendoorn; but it turns out that this fixes
that bug all by itself, as per the added regression test. The reason is
that now get_eclass_for_sort_expr is adding the ORDER BY expression at the
end of EquivalenceClass creation not the start, and so anything that is in
a multi-member EquivalenceClass has already been created with correct
em_nullable_relids. I am suspicious that there are related scenarios in
which we still need to teach get_eclass_for_sort_expr to compute correct
nullable_relids, but am not eager to risk destabilizing either 9.2 or 9.3
to fix bugs that are only hypothetical. So for the moment, do this and
stop here.
Back-patch to 9.2 but not to earlier branches, since they don't exhibit
this bug for lack of join-clause-movement logic that depends on
em_nullable_relids being correct. (We might have to revisit that choice
if any related bugs turn up.) In 9.2, don't change the signature of
make_pathkeys_for_sortclauses nor remove canonicalize_pathkeys, so as
not to risk more plugin breakage than we have to.
2013-04-29 20:49:01 +02:00
|
|
|
List *tlist);
|
2010-10-29 17:52:16 +02:00
|
|
|
extern void initialize_mergeclause_eclasses(PlannerInfo *root,
|
2011-04-10 17:42:00 +02:00
|
|
|
RestrictInfo *restrictinfo);
|
2010-10-29 17:52:16 +02:00
|
|
|
extern void update_mergeclause_eclasses(PlannerInfo *root,
|
2011-04-10 17:42:00 +02:00
|
|
|
RestrictInfo *restrictinfo);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern List *find_mergeclauses_for_pathkeys(PlannerInfo *root,
|
2001-03-22 05:01:46 +01:00
|
|
|
List *pathkeys,
|
2007-01-20 21:45:41 +01:00
|
|
|
bool outer_keys,
|
2001-03-22 05:01:46 +01:00
|
|
|
List *restrictinfos);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern List *select_outer_pathkeys_for_merge(PlannerInfo *root,
|
2007-11-15 22:14:46 +01:00
|
|
|
List *mergeclauses,
|
|
|
|
RelOptInfo *joinrel);
|
2007-01-20 21:45:41 +01:00
|
|
|
extern List *make_inner_pathkeys_for_merge(PlannerInfo *root,
|
2007-11-15 22:14:46 +01:00
|
|
|
List *mergeclauses,
|
|
|
|
List *outer_pathkeys);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern List *truncate_useless_pathkeys(PlannerInfo *root,
|
2001-03-22 05:01:46 +01:00
|
|
|
RelOptInfo *rel,
|
|
|
|
List *pathkeys);
|
2007-04-15 22:09:28 +02:00
|
|
|
extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
|
2001-10-28 07:26:15 +01:00
|
|
|
|
2001-11-05 18:46:40 +01:00
|
|
|
#endif /* PATHS_H */
|