Re: Wrong result when enable_partitionwise_join is on if collation of PartitionKey and Column is different.
Amit Langote <amitlangote09@gmail.com>
From: Amit Langote <amitlangote09@gmail.com>
To: Tender Wang <tndrwang@gmail.com>
Cc: Junwang Zhao <zhjwpku@gmail.com>, jian he <jian.universality@gmail.com>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2024-11-01T06:55:19Z
Lists: pgsql-hackers
Hi,
On Fri, Nov 1, 2024 at 11:39 AM Tender Wang <tndrwang@gmail.com> wrote:
> Amit Langote <amitlangote09@gmail.com> 于2024年10月31日周四 21:09写道:
>> On Wed, Oct 30, 2024 at 9:36 PM Junwang Zhao <zhjwpku@gmail.com> wrote:
>> > On Wed, Oct 30, 2024 at 11:58 AM jian he <jian.universality@gmail.com> wrote:
> In have_partkey_equi_join()
> ...
> if (exprs_known_equal(root, expr1, expr2, btree_opfamily))
> {
> Oid partcoll2 = rel1->part_scheme->partcollation[ipk];
> ....
> I think we should use rel2 here, not rel1.
Hmm, yeah, this should be fixed. Though, this is not a problem
because both rel1 and rel2 would be pointing to the same
PartitionScheme, because otherwise we wouldn't be in
have_partkey_equi_join(). See this in build_joinrel_partition_info():
/*
* We can only consider this join as an input to further partitionwise
* joins if (a) the input relations are partitioned and have
* consider_partitionwise_join=true, (b) the partition schemes match, and
* (c) we can identify an equi-join between the partition keys. Note that
* if it were possible for have_partkey_equi_join to return different
* answers for the same joinrel depending on which join ordering we try
* first, this logic would break. That shouldn't happen, though, because
* of the way the query planner deduces implied equalities and reorders
* the joins. Please see optimizer/README for details.
*/
if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
!outer_rel->consider_partitionwise_join ||
!inner_rel->consider_partitionwise_join ||
outer_rel->part_scheme != inner_rel->part_scheme ||
!have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
sjinfo->jointype, restrictlist))
{
Assert(!IS_PARTITIONED_REL(joinrel));
return;
}
I've changed the condition to match only partcoll1 and exprcoll1, and
if they match, Assert that partcoll2 and exprcoll2 match too. That's
because partcoll1 and partcoll2 would be the same as they are from the
same PartitionScheme and expr1 and expr2 are known equal() so their
collations should match too.
--
Thanks, Amit Langote
Commits
-
Disallow partitionwise join when collations don't match
- 075acdd93388 18.0 landed
- a0cdfc889367 17.1 landed
- f734b6b4d0cc 16.5 landed
- 33040b1715c7 15.9 landed
- 62df5484f976 14.14 landed
- 054701a2b77a 13.17 landed
- 9c4757491683 12.21 landed
-
Disallow partitionwise grouping when collations don't match
- 90fe6251c816 18.0 landed
- b6484ca9535e 17.1 landed
- dd2f8ebee221 16.5 landed
- 0a620659c549 15.9 landed
- 96f9b29a3e1e 14.14 landed
- ff65f695c0d3 13.17 landed
- 46d9be5efb1a 12.21 landed