I wrote:
> I think what this case may show is simply that the consistency
> checking I added to create_mergejoin_plan in 8.3 is too strict.
> Not quite convinced yet though.
After further review I think that is the correct approach to take.
The proximate cause of the problem is that
find_mergeclauses_for_pathkeys is selecting an order for the merge
clauses that corresponds to a noncanonical pathkey list for the
inner relation (to wit, x, y, x). While it would be possible in
this particular example to put the clauses in x, x, y order instead,
I don't think that is necessarily possible in every case. The clause
ordering is constrained by the outer pathkeys and what we have here
is a demonstration that the inner pathkeys needn't match the outer
ones one-to-one. So you could have a clause that references an inner
pathkey that is also referenced by some earlier clause that matches
a different outer pathkey, and there won't be any way to make them
adjacent.
By the time the plan gets to create_mergejoin_plan, the inner pathkey
list has been reduced to canonical form (x, y), but *this does not
represent any actual change in sort order*. (Which is why there's
no actual bug in 8.2 and before, which blithely generate plans that
involve such "incorrect" mergeclause orderings.) So I think we should
just weaken the checks in create_mergejoin_plan to allow such cases,
ie, each mergeclause should be allowed to match any already-used
inner pathkey.
The other approach we could possibly take is to have
find_mergeclauses_for_pathkeys reject candidate mergeclauses that
produce out-of-order inner pathkeys, but that would break at least
this Assert at joinpath.c:272:
/* Should have used them all... */
Assert(list_length(cur_mergeclauses) == list_length(mergeclause_list));
and it'd be rather expensive to test for anyway.
regards, tom lane