diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 27ffd78ce..ab4e7eab1 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -298,6 +298,7 @@ static int GetFillerColIndex(char *filler_col_name, List *col_list); static void RemoveFillerCol(List *filler_list, List *col_list); static int errstate; static void CheckPartitionExpr(Node* expr, int* colCount); +static void CheckPartitionExprInner(Node* expr, int* colCount, bool checkTypeCast); static char* transformIndexOptions(List* list); static void setAccessMethod(Constraint *n); static char* GetValidUserHostId(char* userName, char* hostId); @@ -34568,7 +34569,13 @@ static void checkDeleteRelationError() #ifndef MAX_SUPPORTED_FUNC_FOR_PART_EXPR #define MAX_SUPPORTED_FUNC_FOR_PART_EXPR 25 #endif + static void CheckPartitionExpr(Node* expr, int* colCount) +{ + CheckPartitionExprInner(expr, colCount, true); +} + +static void CheckPartitionExprInner(Node* expr, int* colCount, bool checkTypeCast) { if (expr == NULL) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("The expr can't be NULL"))); @@ -34580,8 +34587,8 @@ static void CheckPartitionExpr(Node* expr, int* colCount) char* name = strVal(linitial(a_expr->name)); if (strcmp(name, "+") != 0 && strcmp(name, "-") != 0 && strcmp(name, "*") != 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("The %s operator is not supported for Partition Expr", name))); - CheckPartitionExpr(a_expr->lexpr, colCount); - CheckPartitionExpr(a_expr->rexpr, colCount); + CheckPartitionExprInner(a_expr->lexpr, colCount, false); + CheckPartitionExprInner(a_expr->rexpr, colCount, false); } else if (expr->type == T_FuncCall) { char* validFuncName[MAX_SUPPORTED_FUNC_FOR_PART_EXPR] = {"abs","ceiling","datediff","day","dayofmonth","dayofweek","dayofyear","extract","floor","hour", "microsecond","minute","mod","month","quarter","second","time_to_sec","to_days","to_seconds","unix_timestamp","weekday","year","yearweek","date_part","div"}; @@ -34597,12 +34604,18 @@ static void CheckPartitionExpr(Node* expr, int* colCount) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("The %s func is not supported for Partition Expr", funcname))); ListCell* cell = NULL; foreach (cell, ((FuncCall*)expr)->args) { - CheckPartitionExpr((Node*)(lfirst(cell)),colCount); + CheckPartitionExprInner((Node*)(lfirst(cell)), colCount, false); } } else if (expr->type == T_ColumnRef) { (*colCount)++; } else if (expr->type == T_A_Const) { return; + } else if (expr->type == T_TypeCast) { + if (checkTypeCast) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("The Partition Expr can't be a Type Cast"))); + } else { + return; + } } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("The Partition Expr can't be %d type", expr->type))); } diff --git a/src/test/regress/expected/hw_partition_datatype.out b/src/test/regress/expected/hw_partition_datatype.out index bc33070b7..605fca5c4 100644 --- a/src/test/regress/expected/hw_partition_datatype.out +++ b/src/test/regress/expected/hw_partition_datatype.out @@ -294,7 +294,29 @@ partition by range(a) partition test_range_datatype_bool_p2 values less than (true) ); ERROR: column a cannot serve as a range partitioning column because of its datatype +--test typecast in the partition expression +CREATE TABLE test_typecast_in_partition_expr_inner ( + event_id NUMBER PRIMARY KEY, + event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL +) +PARTITION BY RANGE (date_part('year'::text, event_timestamp)) +( + partition part1 values less than(2020), + partition part2 values less than(2021) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_typecast_in_partition_expr_inner_pkey" for table "test_typecast_in_partition_expr_inner" +CREATE TABLE test_typecast_in_partition_expr_outer ( + event_id NUMBER PRIMARY KEY, + event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL +) +PARTITION BY RANGE (date_part('year', event_timestamp)::int) +( + partition part1 values less than(2020), + partition part2 values less than(2021) +); +ERROR: The Partition Expr can't be a Type Cast --clean up +drop table test_typecast_in_partition_expr_inner; drop table test_range_datatype_bpchar; drop table test_range_datatype_char; drop table test_range_datatype_charactern; diff --git a/src/test/regress/sql/hw_partition_datatype.sql b/src/test/regress/sql/hw_partition_datatype.sql index a1d887725..e8ca13fa1 100644 --- a/src/test/regress/sql/hw_partition_datatype.sql +++ b/src/test/regress/sql/hw_partition_datatype.sql @@ -196,7 +196,29 @@ partition by range(a) partition test_range_datatype_bool_p2 values less than (true) ); +--test typecast in the partition expression +CREATE TABLE test_typecast_in_partition_expr_inner ( + event_id NUMBER PRIMARY KEY, + event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL +) +PARTITION BY RANGE (date_part('year'::text, event_timestamp)) +( + partition part1 values less than(2020), + partition part2 values less than(2021) +); + +CREATE TABLE test_typecast_in_partition_expr_outer ( + event_id NUMBER PRIMARY KEY, + event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL +) +PARTITION BY RANGE (date_part('year', event_timestamp)::int) +( + partition part1 values less than(2020), + partition part2 values less than(2021) +); + --clean up +drop table test_typecast_in_partition_expr_inner; drop table test_range_datatype_bpchar; drop table test_range_datatype_char; drop table test_range_datatype_charactern;