diff options
| author | Tom Lane | 2013-11-15 21:46:18 +0000 |
|---|---|---|
| committer | Tom Lane | 2013-11-15 21:46:18 +0000 |
| commit | f3b3b8d5be00ebcfade3644fca7a80e25fd88a70 (patch) | |
| tree | 5828466d5ee7adbf7cba8dce58cf755090f26843 /src/include | |
| parent | c7b849a89645212121da480091f87d11fac82495 (diff) | |
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.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/nodes/relation.h | 11 | ||||
| -rw-r--r-- | src/include/optimizer/paths.h | 1 |
2 files changed, 11 insertions, 1 deletions
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index a2853fbf044..6d7b5948cd9 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -150,11 +150,20 @@ typedef struct PlannerInfo /* * all_baserels is a Relids set of all base relids (but not "other" * relids) in the query; that is, the Relids identifier of the final join - * we need to form. + * we need to form. This is computed in make_one_rel, just before we + * start making Paths. */ Relids all_baserels; /* + * nullable_baserels is a Relids set of base relids that are nullable by + * some outer join in the jointree; these are rels that are potentially + * nullable below the WHERE clause, SELECT targetlist, etc. This is + * computed in deconstruct_jointree. + */ + Relids nullable_baserels; + + /* * join_rel_list is a list of all join-relation RelOptInfos we have * considered in this planning run. For small problems we just scan the * list to do lookups, but when there are many join relations we build a diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 9ef93c70c64..96ffdb195fe 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -109,6 +109,7 @@ extern Expr *canonicalize_ec_expression(Expr *expr, extern void reconsider_outer_join_clauses(PlannerInfo *root); extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root, Expr *expr, + Relids nullable_relids, List *opfamilies, Oid opcintype, Oid collation, |
