On 2018/02/28 1:05, Robert Haas wrote: > On Mon, Feb 26, 2018 at 10:59 PM, Amit Langote > <langote_amit...@lab.ntt.co.jp> wrote: >> You may say that partition bounds might have to be different too in this >> case and hence partition-wise join won't occur anyway, but I'm wondering >> if the mismatch of partcollation itself isn't enough to conclude that? > > Yeah, you're right. I think that this is just a bug in partition-wise > join, and that the partition scheme should just be using partcollation > instead of parttypcoll, as in the attached.
Ah, OK. I was missing that there is no need to have both parttypcoll and partcollation in PartitionSchemeData, as the Vars in rel->partexprs are built from a bare PartitionKey (not PartitionSchemeData), and after that point, parttypcoll no longer needs to kept around. I noticed that there is a typo in the patch. + memcpy(part_scheme->partcollation, partkey->parttypcoll, s/parttypcoll/partcollation/g BTW, should there be a relevant test in partition_join.sql? If yes, attached a patch (partitionwise-join-collation-test-1.patch) to add one. Also attached updated version of your patch (fixed the typo). Thanks, Amit
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 60f21711f4..b799e249db 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1891,7 +1891,7 @@ find_partition_scheme(PlannerInfo *root, Relation relation) sizeof(Oid) * partnatts) != 0 || memcmp(partkey->partopcintype, part_scheme->partopcintype, sizeof(Oid) * partnatts) != 0 || - memcmp(partkey->parttypcoll, part_scheme->parttypcoll, + memcmp(partkey->partcollation, part_scheme->partcollation, sizeof(Oid) * partnatts) != 0) continue; @@ -1926,8 +1926,8 @@ find_partition_scheme(PlannerInfo *root, Relation relation) memcpy(part_scheme->partopcintype, partkey->partopcintype, sizeof(Oid) * partnatts); - part_scheme->parttypcoll = (Oid *) palloc(sizeof(Oid) * partnatts); - memcpy(part_scheme->parttypcoll, partkey->parttypcoll, + part_scheme->partcollation = (Oid *) palloc(sizeof(Oid) * partnatts); + memcpy(part_scheme->partcollation, partkey->partcollation, sizeof(Oid) * partnatts); part_scheme->parttyplen = (int16 *) palloc(sizeof(int16) * partnatts); diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index db8de2dfd0..d576aa7350 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -351,7 +351,7 @@ typedef struct PartitionSchemeData int16 partnatts; /* number of partition attributes */ Oid *partopfamily; /* OIDs of operator families */ Oid *partopcintype; /* OIDs of opclass declared input data types */ - Oid *parttypcoll; /* OIDs of collations of partition keys. */ + Oid *partcollation; /* OIDs of partitioning collations */ /* Cached information about partition key data types. */ int16 *parttyplen;
diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 4fccd9ae54..6323a13777 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -1869,3 +1869,31 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c); -> Seq Scan on prt1_n_p2 t1_1 (10 rows) +-- +-- No partition-wise join if partitioning collation doesn't match +-- +CREATE TABLE posix_text (a text) PARTITION BY RANGE (a COLLATE "POSIX"); +CREATE TABLE posix_text1 PARTITION OF posix_text FOR VALUES FROM ('a') TO ('m'); +CREATE TABLE posix_text2 PARTITION OF posix_text FOR VALUES FROM ('m') TO ('z '); +CREATE TABLE c_text (a text) PARTITION BY RANGE (a COLLATE "C"); +CREATE TABLE c_text1 PARTITION OF c_text FOR VALUES FROM ('a') TO ('m'); +CREATE TABLE c_text2 PARTITION OF c_text FOR VALUES FROM ('m') TO ('z '); +EXPLAIN (COSTS OFF) +SELECT * FROM posix_text p JOIN c_text c ON (p.a = c.a); + QUERY PLAN +----------------------------------------------- + Merge Join + Merge Cond: (p.a = c.a) + -> Sort + Sort Key: p.a + -> Append + -> Seq Scan on posix_text1 p + -> Seq Scan on posix_text2 p_1 + -> Sort + Sort Key: c.a + -> Append + -> Seq Scan on c_text1 c + -> Seq Scan on c_text2 c_1 +(12 rows) + +DROP TABLE posix_text, c_text; diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql index a2d8b1be55..0df7df487d 100644 --- a/src/test/regress/sql/partition_join.sql +++ b/src/test/regress/sql/partition_join.sql @@ -384,3 +384,19 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOI -- partitioned table EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c); + +-- +-- No partition-wise join if partitioning collation doesn't match +-- +CREATE TABLE posix_text (a text) PARTITION BY RANGE (a COLLATE "POSIX"); +CREATE TABLE posix_text1 PARTITION OF posix_text FOR VALUES FROM ('a') TO ('m'); +CREATE TABLE posix_text2 PARTITION OF posix_text FOR VALUES FROM ('m') TO ('z '); + +CREATE TABLE c_text (a text) PARTITION BY RANGE (a COLLATE "C"); +CREATE TABLE c_text1 PARTITION OF c_text FOR VALUES FROM ('a') TO ('m'); +CREATE TABLE c_text2 PARTITION OF c_text FOR VALUES FROM ('m') TO ('z '); + +EXPLAIN (COSTS OFF) +SELECT * FROM posix_text p JOIN c_text c ON (p.a = c.a); + +DROP TABLE posix_text, c_text;