You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudberry.apache.org by ma...@apache.org on 2025/02/08 05:23:50 UTC

(cloudberry) branch main updated: Fix partition creation to handle MAXVALUE in subpartition bounds

This is an automated email from the ASF dual-hosted git repository.

maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/main by this push:
     new e9bcc8db38 Fix partition creation to handle MAXVALUE in subpartition bounds
e9bcc8db38 is described below

commit e9bcc8db38589da414c64207f19084a3e407ba24
Author: Zhang Mingli <av...@gmail.com>
AuthorDate: Thu Feb 6 13:44:05 2025 +0800

    Fix partition creation to handle MAXVALUE in subpartition bounds
    
    Previously, the simplified partition creation syntax in GPDB did not
    properly handle MAXVALUE as a boundary value for subpartitions.
    
    The fix allows users to define subpartitions with MAXVALUE boundaries
    using the simplified partition creation syntax, maintaining
    compatibility with existing partition functionality.
    
    During the fix, it was also identified that MINVALUE has a similar
    issue.
    However, addressing MINVALUE is more complex due to the current
    implementation of the START/EVERY/END grammar, which only considers
    the end boundary situation.
    A broader refactor of the partition creation logic may be required to
    properly support MINVALUE in subpartition definitions.
    
    Fixes: https://github.com/apache/cloudberry/issues/795
    
    Authored-by: Zhang Mingli avamingli@gmail.com
---
 src/backend/parser/parse_partition_gp.c           | 88 ++++++++++++++++++-----
 src/test/regress/expected/partition.out           | 25 +++++++
 src/test/regress/expected/partition_optimizer.out | 25 +++++++
 src/test/regress/sql/partition.sql                | 16 +++++
 4 files changed, 137 insertions(+), 17 deletions(-)

diff --git a/src/backend/parser/parse_partition_gp.c b/src/backend/parser/parse_partition_gp.c
index c6696a5df7..5313acb3c7 100644
--- a/src/backend/parser/parse_partition_gp.c
+++ b/src/backend/parser/parse_partition_gp.c
@@ -566,27 +566,79 @@ initPartEveryIterator(ParseState *pstate, PartitionKeyData *partkey, const char
 	if (end)
 	{
 		Const	   *endConst;
+		Node	*expr = end;
+		PartitionRangeDatum *prd = NULL;
 
-		endConst = transformPartitionBoundValue(pstate,
-												end,
-												part_col_name,
-												part_col_typid,
-												part_col_typmod,
-												part_col_collation);
-		if (endConst->constisnull)
-			ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-				 errmsg("cannot use NULL with range partition specification"),
-				 parser_errposition(pstate, exprLocation(end))));
+		/*
+		 * Infinite range bounds -- "minvalue" and "maxvalue" -- get passed in
+		 * as ColumnRefs.
+		 */
+		if (IsA(expr, ColumnRef))
+		{
+			ColumnRef  *cref = (ColumnRef *) expr;
+			char	   *cname = NULL;
 
-		if (endInclusive)
-			convert_exclusive_start_inclusive_end(endConst,
-												  part_col_typid, part_col_typmod,
-												  false);
-		if (endConst->constisnull)
+			/*
+			 * There should be a single field named either "minvalue" or
+			 * "maxvalue".
+			 */
+			if (list_length(cref->fields) == 1 &&
+				IsA(linitial(cref->fields), String))
+				cname = strVal(linitial(cref->fields));
+
+			if (cname == NULL)
+			{
+				/*
+				 * ColumnRef is not in the desired single-field-name form. For
+				 * consistency between all partition strategies, let the
+				 * expression transformation report any errors rather than
+				 * doing it ourselves.
+				 */
+			}
+			else if (strcmp("minvalue", cname) == 0)
+			{
+				/* FIXME: Cloud be possible when multiple multi-dimension? */
+				prd = makeNode(PartitionRangeDatum);
+				prd->kind = PARTITION_RANGE_DATUM_MINVALUE;
+				prd->value = NULL;
+			}
+			else if (strcmp("maxvalue", cname) == 0)
+			{
+				prd = makeNode(PartitionRangeDatum);
+				prd->kind = PARTITION_RANGE_DATUM_MAXVALUE;
+				prd->value = NULL;
+			}
+		}
+		if (prd)
+		{
+
+			end = (Node *) prd;
 			isEndValMaxValue = true;
 
-		endVal = endConst->constvalue;
+		}
+		else
+		{
+			endConst = transformPartitionBoundValue(pstate,
+													end,
+													part_col_name,
+													part_col_typid,
+													part_col_typmod,
+													part_col_collation);
+			if (endConst->constisnull)
+				ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+					 errmsg("cannot use NULL with range partition specification"),
+					 parser_errposition(pstate, exprLocation(end))));
+
+			if (endInclusive)
+				convert_exclusive_start_inclusive_end(endConst,
+													  part_col_typid, part_col_typmod,
+													  false);
+			if (endConst->constisnull)
+				isEndValMaxValue = true;
+
+			endVal = endConst->constvalue;
+		}
 	}
 
 	iter = palloc0(sizeof(PartEveryIterator));
@@ -685,6 +737,8 @@ initPartEveryIterator(ParseState *pstate, PartitionKeyData *partkey, const char
 	iter->currStart = (Datum) 0;
 	iter->called = false;
 	iter->endReached = false;
+	if (iter->isEndValMaxValue)
+		iter->endReached = false;
 
 	iter->pstate = pstate;
 	iter->end_location = exprLocation(end);
diff --git a/src/test/regress/expected/partition.out b/src/test/regress/expected/partition.out
index 124c31ea50..bed83a3d3d 100755
--- a/src/test/regress/expected/partition.out
+++ b/src/test/regress/expected/partition.out
@@ -6653,3 +6653,28 @@ NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as
 HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
 -- Check with other Partition syntax
 CREATE TABLE empty_partition2(i int, j int) DISTRIBUTED BY (i) PARTITION BY range(i);
+-- https://github.com/apache/cloudberry/issues/795
+CREATE TABLE t_issue_795_par (
+  name character varying,
+  last_modified_date timestamp without time zone
+)
+WITH (appendoptimized=true, orientation=column, compresslevel=1)
+DISTRIBUTED BY (name)
+PARTITION BY RANGE (last_modified_date)
+(
+    PARTITION partition_202411 START ('2024-11-01 00:00:00') INCLUSIVE END ('2024-12-01 00:00:00') EXCLUSIVE,
+    PARTITION partition_max START ('2024-12-01 00:00:00') INCLUSIVE END (MAXVALUE)
+);
+\d+ t_issue_795_par
+                                                                  Partitioned table "public.t_issue_795_par"
+       Column       |            Type             | Collation | Nullable | Default | Storage  | Stats target | Compression Type | Compression Level | Block Size | Description 
+--------------------+-----------------------------+-----------+----------+---------+----------+--------------+------------------+-------------------+------------+-------------
+ name               | character varying           |           |          |         | extended |              | zlib             | 1                 | 32768      | 
+ last_modified_date | timestamp without time zone |           |          |         | plain    |              | zlib             | 1                 | 32768      | 
+Partition key: RANGE (last_modified_date)
+Partitions: t_issue_795_par_1_prt_partition_202411 FOR VALUES FROM ('Fri Nov 01 00:00:00 2024') TO ('Sun Dec 01 00:00:00 2024'),
+            t_issue_795_par_1_prt_partition_max FOR VALUES FROM ('Sun Dec 01 00:00:00 2024') TO (MAXVALUE)
+Distributed by: (name)
+Options: compresslevel=1
+
+DROP TABLE t_issue_795_par;
diff --git a/src/test/regress/expected/partition_optimizer.out b/src/test/regress/expected/partition_optimizer.out
index 274689c513..2ba98125ec 100755
--- a/src/test/regress/expected/partition_optimizer.out
+++ b/src/test/regress/expected/partition_optimizer.out
@@ -6656,3 +6656,28 @@ NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as
 HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
 -- Check with other Partition syntax
 CREATE TABLE empty_partition2(i int, j int) DISTRIBUTED BY (i) PARTITION BY range(i);
+-- https://github.com/apache/cloudberry/issues/795
+CREATE TABLE t_issue_795_par (
+  name character varying,
+  last_modified_date timestamp without time zone
+)
+WITH (appendoptimized=true, orientation=column, compresslevel=1)
+DISTRIBUTED BY (name)
+PARTITION BY RANGE (last_modified_date)
+(
+    PARTITION partition_202411 START ('2024-11-01 00:00:00') INCLUSIVE END ('2024-12-01 00:00:00') EXCLUSIVE,
+    PARTITION partition_max START ('2024-12-01 00:00:00') INCLUSIVE END (MAXVALUE)
+);
+\d+ t_issue_795_par
+                                                                  Partitioned table "public.t_issue_795_par"
+       Column       |            Type             | Collation | Nullable | Default | Storage  | Stats target | Compression Type | Compression Level | Block Size | Description 
+--------------------+-----------------------------+-----------+----------+---------+----------+--------------+------------------+-------------------+------------+-------------
+ name               | character varying           |           |          |         | extended |              | zlib             | 1                 | 32768      | 
+ last_modified_date | timestamp without time zone |           |          |         | plain    |              | zlib             | 1                 | 32768      | 
+Partition key: RANGE (last_modified_date)
+Partitions: t_issue_795_par_1_prt_partition_202411 FOR VALUES FROM ('Fri Nov 01 00:00:00 2024') TO ('Sun Dec 01 00:00:00 2024'),
+            t_issue_795_par_1_prt_partition_max FOR VALUES FROM ('Sun Dec 01 00:00:00 2024') TO (MAXVALUE)
+Distributed by: (name)
+Options: compresslevel=1
+
+DROP TABLE t_issue_795_par;
diff --git a/src/test/regress/sql/partition.sql b/src/test/regress/sql/partition.sql
index 43c55a4b72..dc876f7304 100644
--- a/src/test/regress/sql/partition.sql
+++ b/src/test/regress/sql/partition.sql
@@ -4230,3 +4230,19 @@ CREATE TABLE empty_partition(i int, j int) PARTITION BY range(i);
 
 -- Check with other Partition syntax
 CREATE TABLE empty_partition2(i int, j int) DISTRIBUTED BY (i) PARTITION BY range(i);
+
+-- https://github.com/apache/cloudberry/issues/795
+CREATE TABLE t_issue_795_par (
+  name character varying,
+  last_modified_date timestamp without time zone
+)
+WITH (appendoptimized=true, orientation=column, compresslevel=1)
+DISTRIBUTED BY (name)
+PARTITION BY RANGE (last_modified_date)
+(
+    PARTITION partition_202411 START ('2024-11-01 00:00:00') INCLUSIVE END ('2024-12-01 00:00:00') EXCLUSIVE,
+    PARTITION partition_max START ('2024-12-01 00:00:00') INCLUSIVE END (MAXVALUE)
+);
+
+\d+ t_issue_795_par
+DROP TABLE t_issue_795_par;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cloudberry.apache.org
For additional commands, e-mail: commits-help@cloudberry.apache.org