A 库下处理hash分区遇到null值输入报错问题
This commit is contained in:
@ -404,6 +404,7 @@ Oid getHashPartitionOid(PartitionMap* partMap, Const** partKeyValue, int32* part
|
||||
Oid result = InvalidOid;
|
||||
int keyNums = 0;
|
||||
int hit = -1;
|
||||
bool hasNull = false;
|
||||
|
||||
Assert(PointerIsValid(partMap));
|
||||
Assert(PointerIsValid(partKeyValue));
|
||||
@ -417,6 +418,10 @@ Oid getHashPartitionOid(PartitionMap* partMap, Const** partKeyValue, int32* part
|
||||
uint32 hash_value = 0;
|
||||
while (i < keyNums) {
|
||||
if (partKeyValue[i]->constisnull) {
|
||||
if (DB_IS_CMPT(A_FORMAT)) {
|
||||
hasNull = true;
|
||||
break;
|
||||
}
|
||||
if (PointerIsValid(partSeq)) {
|
||||
*partSeq = hit;
|
||||
}
|
||||
@ -428,16 +433,19 @@ Oid getHashPartitionOid(PartitionMap* partMap, Const** partKeyValue, int32* part
|
||||
i++;
|
||||
}
|
||||
|
||||
hit = hash_value % (uint32)(hashPartMap->hashElementsNum);
|
||||
hit = hashPartMap->hashElementsNum - hit - 1;
|
||||
if (hasNull && DB_IS_CMPT(A_FORMAT)) {
|
||||
/* If null exists for hash partition, force route to first partition */
|
||||
hit = 0;
|
||||
} else {
|
||||
hit = hash_value % (uint32)(hashPartMap->hashElementsNum);
|
||||
hit = hashPartMap->hashElementsNum - hit - 1;
|
||||
}
|
||||
|
||||
if (PointerIsValid(partSeq)) {
|
||||
*partSeq = hit;
|
||||
}
|
||||
|
||||
if (hit >= 0) {
|
||||
result = hashPartMap->hashElements[hit].partitionOid;
|
||||
}
|
||||
result = hashPartMap->hashElements[hit].partitionOid;
|
||||
|
||||
decre_partmap_refcount(partMap);
|
||||
return result;
|
||||
|
||||
@ -990,8 +990,21 @@ static PruningResult* partitionPruningFromNullTest(PartitionType partType, NullT
|
||||
return result;
|
||||
}
|
||||
if (expr->nulltesttype != IS_NULL) {
|
||||
/* For IS_NOT_NULL, we don't try to verify that the first partition is all NULL,
|
||||
* so do not perform pruning here.
|
||||
*/
|
||||
result->state = PRUNING_RESULT_FULL;
|
||||
} else {
|
||||
if (DB_IS_CMPT(A_FORMAT)) {
|
||||
/* Clause hash partition for null value always route to first partition,
|
||||
* so for IS_NULL, we return the first partition.
|
||||
*/
|
||||
result->isPbeSinlePartition = true;
|
||||
result->boundary = NULL;
|
||||
result->state = PRUNING_RESULT_SUBSET;
|
||||
result->bm_rangeSelectedPartitions = bms_make_singleton(0);
|
||||
return result;
|
||||
}
|
||||
result->state = PRUNING_RESULT_EMPTY;
|
||||
}
|
||||
result->isPbeSinlePartition = false;
|
||||
|
||||
@ -24,15 +24,18 @@ partition by hash (a)
|
||||
insert into test_partition_for_null_hash values (0, 0, 0, 0);
|
||||
insert into test_partition_for_null_hash values (1, 1, 1, 1);
|
||||
insert into test_partition_for_null_hash values (5, 5, 5, 5);
|
||||
-- failed: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (null, null, null, null);
|
||||
ERROR: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (0, null, null, null);
|
||||
-- failed: The partition number is invalid or out-of-range
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition for (null) order by 1, 2, 3, 4;
|
||||
ERROR: Cannot find partition by the value
|
||||
DETAIL: N/A.
|
||||
a | b | c | d
|
||||
---+---+---+---
|
||||
1 | 1 | 1 | 1
|
||||
| | |
|
||||
(2 rows)
|
||||
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition for (0) order by 1, 2, 3, 4;
|
||||
a | b | c | d
|
||||
@ -41,17 +44,17 @@ select * from test_partition_for_null_hash partition for (0) order by 1, 2, 3, 4
|
||||
0 | | |
|
||||
(2 rows)
|
||||
|
||||
-- failed: The partition number is invalid or out-of-range
|
||||
alter table test_partition_for_null_hash rename partition for (null) to test_partition_for_null_hash_part1;
|
||||
ERROR: The partition number is invalid or out-of-range
|
||||
-- success
|
||||
alter table test_partition_for_null_hash rename partition for (null) to test_partition_for_null_hash_part1;
|
||||
-- failed, same partition name test_partition_for_null_hash_part1 is already exists
|
||||
alter table test_partition_for_null_hash rename partition for (0) to test_partition_for_null_hash_part1;
|
||||
ERROR: partition "test_partition_for_null_hash_part1" of relation "test_partition_for_null_hash" already exists
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition (test_partition_for_null_hash_part1) order by 1, 2, 3, 4;
|
||||
a | b | c | d
|
||||
---+---+---+---
|
||||
0 | 0 | 0 | 0
|
||||
0 | | |
|
||||
1 | 1 | 1 | 1
|
||||
| | |
|
||||
(2 rows)
|
||||
|
||||
alter table test_partition_for_null_hash drop partition for (NULL);
|
||||
@ -61,10 +64,10 @@ ERROR: Droping hash partition is unsupported.
|
||||
CREATE TABLE select_hash_partition_table_000_3(
|
||||
C_CHAR_1 CHAR(1),
|
||||
C_CHAR_2 CHAR(10),
|
||||
C_CHAR_3 CHAR(102400),
|
||||
C_CHAR_3 CHAR(20),
|
||||
C_VARCHAR_1 VARCHAR(1),
|
||||
C_VARCHAR_2 VARCHAR(10),
|
||||
C_VARCHAR_3 VARCHAR(1024),
|
||||
C_VARCHAR_3 VARCHAR(20),
|
||||
C_INT INTEGER,
|
||||
C_BIGINT BIGINT,
|
||||
C_SMALLINT SMALLINT,
|
||||
@ -95,10 +98,17 @@ INSERT INTO select_hash_partition_table_000_3 VALUES('I','IJK','IJKLMNO','i','ij
|
||||
INSERT INTO select_hash_partition_table_000_3 VALUES('I','IJK','IJKLMNO','i','ijk','ijklmno',1100,999999,99,9.9,9.99,9.999,'2000-09-09','2000-09-09 09:09:09','2000-09-09 09:09:09+09');
|
||||
INSERT INTO select_hash_partition_table_000_3 VALUES('I','IJK','IJKLMNO','i','ijk','ijklmno',1600,999999,99,9.9,9.99,9.999,'2000-09-09','2000-09-09 09:09:09','2000-09-09 09:09:09+09');
|
||||
select * from select_hash_partition_table_000_3 partition for (NULL) order by C_INT;
|
||||
ERROR: Cannot find partition by the value
|
||||
DETAIL: N/A.
|
||||
c_char_1 | c_char_2 | c_char_3 | c_varchar_1 | c_varchar_2 | c_varchar_3 | c_int | c_bigint | c_smallint | c_float | c_numeric | c_dp | c_date | c_ts_without | c_ts_with
|
||||
----------+------------+----------------------+-------------+-------------+-------------+-------+----------+------------+---------+-----------+-------+--------------------------+--------------------------+------------------------------
|
||||
A | ABC | ABCDEFG | a | abc | abcdefg | 111 | 111111 | 11 | 1.1 | 1.11000 | 1.111 | Sat Jan 01 00:00:00 2000 | Sat Jan 01 01:01:01 2000 | Fri Dec 31 16:01:01 1999 PST
|
||||
E | EFG | EFGHIJK | e | efg | efghijk | 555 | 555555 | 55 | 5.5 | 5.55000 | 5.555 | Fri May 05 00:00:00 2000 | Fri May 05 05:05:05 2000 | Thu May 04 17:05:05 2000 PDT
|
||||
F | FGH | FGHIJKL | f | fgh | fghijkl | 666 | 666666 | 66 | 6.6 | 6.66000 | 6.666 | Tue Jun 06 00:00:00 2000 | Tue Jun 06 06:06:06 2000 | Mon Jun 05 17:06:06 2000 PDT
|
||||
G | GHI | GHIJKLM | g | ghi | ghijklm | 777 | 777777 | 77 | 7.7 | 7.77000 | 7.777 | Fri Jul 07 00:00:00 2000 | Fri Jul 07 07:07:07 2000 | Thu Jul 06 17:07:07 2000 PDT
|
||||
I | IJK | IJKLMNO | i | ijk | ijklmno | 999 | 999999 | 99 | 9.9 | 9.99000 | 9.999 | Sat Sep 09 00:00:00 2000 | Sat Sep 09 09:09:09 2000 | Fri Sep 08 17:09:09 2000 PDT
|
||||
I | IJK | IJKLMNO | i | ijk | ijklmno | 999 | 999999 | 99 | 9.9 | 9.99000 | 9.999 | Sat Sep 09 00:00:00 2000 | Sat Sep 09 09:09:09 2000 | Fri Sep 08 17:09:09 2000 PDT
|
||||
(6 rows)
|
||||
|
||||
alter table select_hash_partition_table_000_3 rename partition for (NULL) to select_hash_partition_table_000_3_p1;
|
||||
ERROR: The partition number is invalid or out-of-range
|
||||
alter table select_hash_partition_table_000_3 drop partition for (NULL);
|
||||
ERROR: Droping hash partition is unsupported.
|
||||
CREATE TABLE partition_wise_join_table_001_1 (ID INT NOT NULL,NAME VARCHAR(50) NOT NULL,SCORE NUMERIC(4,1),BIRTHDAY TIMESTAMP WITHOUT TIME ZONE,ADDRESS TEXT,SALARY double precision,RANK SMALLINT)
|
||||
|
||||
@ -22,9 +22,8 @@ select * from test_partition_for_null_hash order by a;
|
||||
5 | 5 | 5 | 5
|
||||
(6 rows)
|
||||
|
||||
-- failed: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (null, null, null, null);
|
||||
ERROR: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (0, null, null, null);
|
||||
CREATE TABLE select_hash_partition_table_000_3(
|
||||
@ -180,6 +179,108 @@ select count(*) from hw_partition_select_test;
|
||||
4
|
||||
(1 row)
|
||||
|
||||
create table hw_hash_partition_inert_null (c1 int, c2 timestamp)
|
||||
partition by hash (c2)
|
||||
(
|
||||
partition hw_hash_partition_inert_null_p1,
|
||||
partition hw_hash_partition_inert_null_p2,
|
||||
partition hw_hash_partition_inert_null_p3,
|
||||
partition hw_hash_partition_inert_null_p4,
|
||||
partition hw_hash_partition_inert_null_p5
|
||||
);
|
||||
insert into hw_hash_partition_inert_null values (generate_series(1, 1000), null);
|
||||
insert into hw_hash_partition_inert_null values (1001, '2025-02-24 00:00:00'::timestamp);
|
||||
insert into hw_hash_partition_inert_null values (1002, '2024-01-01 00:00:00'::timestamp);
|
||||
insert into hw_hash_partition_inert_null values (1003, '2024-06-06 00:00:00'::timestamp);
|
||||
select p.relname, ta.row_count from (select tableoid::regclass as partition_id, count(*) as row_count from hw_hash_partition_inert_null group by partition_id) as ta left join pg_partition p on p.oid = ta.partition_id order by p.oid;
|
||||
relname | row_count
|
||||
---------------------------------+-----------
|
||||
hw_hash_partition_inert_null_p1 | 1000
|
||||
hw_hash_partition_inert_null_p2 | 1
|
||||
hw_hash_partition_inert_null_p3 | 1
|
||||
hw_hash_partition_inert_null_p4 | 1
|
||||
(4 rows)
|
||||
|
||||
drop table hw_hash_partition_inert_null;
|
||||
-- non index partition key
|
||||
drop table if exists t1_part;
|
||||
NOTICE: table "t1_part" does not exist, skipping
|
||||
create table t1_part (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
insert into t1_part values (generate_series(1, 1000), null);
|
||||
insert into t1_part values (1001, generate_series(1, 100));
|
||||
explain (costs off) select * from t1_part where c2 is null;
|
||||
QUERY PLAN
|
||||
---------------------------------
|
||||
Partitioned Seq Scan on t1_part
|
||||
Filter: (c2 IS NULL)
|
||||
Selected Partitions: 1
|
||||
(3 rows)
|
||||
|
||||
explain (costs off) select * from t1_part where c2 = 20;
|
||||
QUERY PLAN
|
||||
---------------------------------
|
||||
Partitioned Seq Scan on t1_part
|
||||
Filter: (c2 = 20)
|
||||
Selected Partitions: 5
|
||||
(3 rows)
|
||||
|
||||
drop table t1_part;
|
||||
-- local index partition key
|
||||
drop table if exists t1_partindex;
|
||||
NOTICE: table "t1_partindex" does not exist, skipping
|
||||
create table t1_partindex (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
create index t1_partindex_c2_ind on t1_partindex (c2) local;
|
||||
insert into t1_partindex values (generate_series(1, 1000), null);
|
||||
insert into t1_partindex values (2000, generate_series(1, 100));
|
||||
explain (costs off) select * from t1_partindex where c2 is null;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------
|
||||
Partitioned Bitmap Heap Scan on t1_partindex
|
||||
Recheck Cond: (c2 IS NULL)
|
||||
Selected Partitions: 1
|
||||
-> Partitioned Bitmap Index Scan on t1_partindex_c2_ind
|
||||
Index Cond: (c2 IS NULL)
|
||||
Selected Partitions: 1
|
||||
(6 rows)
|
||||
|
||||
explain (costs off) select * from t1_partindex where c2 = 20;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------
|
||||
Partitioned Bitmap Heap Scan on t1_partindex
|
||||
Recheck Cond: (c2 = 20)
|
||||
Selected Partitions: 5
|
||||
-> Partitioned Bitmap Index Scan on t1_partindex_c2_ind
|
||||
Index Cond: (c2 = 20)
|
||||
Selected Partitions: 5
|
||||
(6 rows)
|
||||
|
||||
drop table t1_partindex;
|
||||
-- global index partition key
|
||||
drop table if exists t1_partindex_global;
|
||||
NOTICE: table "t1_partindex_global" does not exist, skipping
|
||||
create table t1_partindex_global (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
create index t1_partindex_global_c2_ind on t1_partindex_global (c2);
|
||||
insert into t1_partindex_global values (generate_series(1, 1000), null);
|
||||
insert into t1_partindex_global values (2000, generate_series(1, 100));
|
||||
explain (costs off) select * from t1_partindex_global where c2 is null;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Bitmap Heap Scan on t1_partindex_global
|
||||
Recheck Cond: (c2 IS NULL)
|
||||
-> Bitmap Index Scan on t1_partindex_global_c2_ind
|
||||
Index Cond: (c2 IS NULL)
|
||||
(4 rows)
|
||||
|
||||
explain (costs off) select * from t1_partindex_global where c2 = 20;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Bitmap Heap Scan on t1_partindex_global
|
||||
Recheck Cond: (c2 = 20)
|
||||
-> Bitmap Index Scan on t1_partindex_global_c2_ind
|
||||
Index Cond: (c2 = 20)
|
||||
(4 rows)
|
||||
|
||||
drop table t1_partindex_global;
|
||||
drop schema FVT_COMPRESS_QWER cascade;
|
||||
NOTICE: drop cascades to 9 other objects
|
||||
DETAIL: drop cascades to table test_partition_for_null_hash
|
||||
|
||||
@ -31,21 +31,21 @@ insert into test_partition_for_null_hash values (0, 0, 0, 0);
|
||||
insert into test_partition_for_null_hash values (1, 1, 1, 1);
|
||||
insert into test_partition_for_null_hash values (5, 5, 5, 5);
|
||||
|
||||
-- failed: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (null, null, null, null);
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (0, null, null, null);
|
||||
|
||||
|
||||
-- failed: The partition number is invalid or out-of-range
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition for (null) order by 1, 2, 3, 4;
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition for (0) order by 1, 2, 3, 4;
|
||||
|
||||
|
||||
-- failed: The partition number is invalid or out-of-range
|
||||
alter table test_partition_for_null_hash rename partition for (null) to test_partition_for_null_hash_part1;
|
||||
-- success
|
||||
alter table test_partition_for_null_hash rename partition for (null) to test_partition_for_null_hash_part1;
|
||||
-- failed, same partition name test_partition_for_null_hash_part1 is already exists
|
||||
alter table test_partition_for_null_hash rename partition for (0) to test_partition_for_null_hash_part1;
|
||||
-- success
|
||||
select * from test_partition_for_null_hash partition (test_partition_for_null_hash_part1) order by 1, 2, 3, 4;
|
||||
@ -56,10 +56,10 @@ alter table test_partition_for_null_hash drop partition for (0);
|
||||
CREATE TABLE select_hash_partition_table_000_3(
|
||||
C_CHAR_1 CHAR(1),
|
||||
C_CHAR_2 CHAR(10),
|
||||
C_CHAR_3 CHAR(102400),
|
||||
C_CHAR_3 CHAR(20),
|
||||
C_VARCHAR_1 VARCHAR(1),
|
||||
C_VARCHAR_2 VARCHAR(10),
|
||||
C_VARCHAR_3 VARCHAR(1024),
|
||||
C_VARCHAR_3 VARCHAR(20),
|
||||
C_INT INTEGER,
|
||||
C_BIGINT BIGINT,
|
||||
C_SMALLINT SMALLINT,
|
||||
|
||||
@ -13,7 +13,7 @@ insert into test_partition_for_null_hash values (1, 1, 1, 1);
|
||||
insert into test_partition_for_null_hash values (5, 5, 5, 5);
|
||||
insert into test_partition_for_null_hash select * from test_partition_for_null_hash;
|
||||
select * from test_partition_for_null_hash order by a;
|
||||
-- failed: inserted partition key does not map to any table partition
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (null, null, null, null);
|
||||
-- success
|
||||
insert into test_partition_for_null_hash values (0, null, null, null);
|
||||
@ -148,4 +148,58 @@ insert into hw_partition_select_test values(555);
|
||||
insert into hw_partition_select_test values(888);
|
||||
insert into hw_partition_select_test values(100);
|
||||
select count(*) from hw_partition_select_test;
|
||||
|
||||
create table hw_hash_partition_inert_null (c1 int, c2 timestamp)
|
||||
partition by hash (c2)
|
||||
(
|
||||
partition hw_hash_partition_inert_null_p1,
|
||||
partition hw_hash_partition_inert_null_p2,
|
||||
partition hw_hash_partition_inert_null_p3,
|
||||
partition hw_hash_partition_inert_null_p4,
|
||||
partition hw_hash_partition_inert_null_p5
|
||||
);
|
||||
insert into hw_hash_partition_inert_null values (generate_series(1, 1000), null);
|
||||
insert into hw_hash_partition_inert_null values (1001, '2025-02-24 00:00:00'::timestamp);
|
||||
insert into hw_hash_partition_inert_null values (1002, '2024-01-01 00:00:00'::timestamp);
|
||||
insert into hw_hash_partition_inert_null values (1003, '2024-06-06 00:00:00'::timestamp);
|
||||
select p.relname, ta.row_count from (select tableoid::regclass as partition_id, count(*) as row_count from hw_hash_partition_inert_null group by partition_id) as ta left join pg_partition p on p.oid = ta.partition_id order by p.oid;
|
||||
drop table hw_hash_partition_inert_null;
|
||||
|
||||
-- non index partition key
|
||||
drop table if exists t1_part;
|
||||
create table t1_part (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
insert into t1_part values (generate_series(1, 1000), null);
|
||||
insert into t1_part values (1001, generate_series(1, 100));
|
||||
|
||||
explain (costs off) select * from t1_part where c2 is null;
|
||||
explain (costs off) select * from t1_part where c2 = 20;
|
||||
|
||||
drop table t1_part;
|
||||
|
||||
-- local index partition key
|
||||
drop table if exists t1_partindex;
|
||||
create table t1_partindex (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
create index t1_partindex_c2_ind on t1_partindex (c2) local;
|
||||
|
||||
insert into t1_partindex values (generate_series(1, 1000), null);
|
||||
insert into t1_partindex values (2000, generate_series(1, 100));
|
||||
|
||||
explain (costs off) select * from t1_partindex where c2 is null;
|
||||
explain (costs off) select * from t1_partindex where c2 = 20;
|
||||
|
||||
drop table t1_partindex;
|
||||
|
||||
-- global index partition key
|
||||
drop table if exists t1_partindex_global;
|
||||
create table t1_partindex_global (c1 int, c2 int) partition by hash (c2) partitions 6;
|
||||
create index t1_partindex_global_c2_ind on t1_partindex_global (c2);
|
||||
|
||||
insert into t1_partindex_global values (generate_series(1, 1000), null);
|
||||
insert into t1_partindex_global values (2000, generate_series(1, 100));
|
||||
|
||||
explain (costs off) select * from t1_partindex_global where c2 is null;
|
||||
explain (costs off) select * from t1_partindex_global where c2 = 20;
|
||||
|
||||
drop table t1_partindex_global;
|
||||
|
||||
drop schema FVT_COMPRESS_QWER cascade;
|
||||
Reference in New Issue
Block a user