diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index c66a9dad8..a05b870e5 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -118,6 +118,13 @@ static void AddDefaultExprNode(ParseState* pstate) int fieldCnt = rdAtt->natts; refState->constValues = (Const**)palloc0(sizeof(Const) * fieldCnt); + eval_const_expressions_context context; + context.boundParams = nullptr; + context.root = nullptr; + context.active_fns = NIL; + context.case_val = NULL; + context.estimate = false; + for (int i = 0; i < fieldCnt; ++i) { Form_pg_attribute attTup = rdAtt->attrs[i]; if (IsAutoIncrementColumn(rdAtt, i + 1)) { @@ -126,9 +133,21 @@ static void AddDefaultExprNode(ParseState* pstate) } else if (ISGENERATEDCOL(rdAtt, i)) { refState->constValues[i] = nullptr; } else { - Node* expr = build_column_default(relation, i + 1, true); - if (expr && IsA(expr, Const)) { - refState->constValues[i] = (Const*)expr; + Node* node = build_column_default(relation, i + 1, true); + if (node == nullptr) { + refState->constValues[i] = nullptr; + } else if (IsA(node, Const)) { + refState->constValues[i] = (Const*)node; + } else if (IsA(node, FuncExpr)) { + FuncExpr* expr = (FuncExpr*)node; + List* args = expr->args; + Expr* simple = simplify_function(expr->funcid, expr->funcresulttype, exprTypmod((const Node*)expr), + expr->funccollid, expr->inputcollid, &args, true, false, &context); + if (simple && IsA(simple, Const)) { + refState->constValues[i] = (Const*)simple; + } else { + refState->constValues[i] = nullptr; + } } else { refState->constValues[i] = nullptr; } diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index 2c32ac8a6..f91f441c2 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -64,14 +64,6 @@ typedef struct { AggClauseCosts* costs; } count_agg_clauses_context; -typedef struct { - ParamListInfo boundParams; - PlannerInfo* root; - List* active_fns; - Node* case_val; - bool estimate; -} eval_const_expressions_context; - typedef struct { int nargs; List* args; @@ -125,8 +117,6 @@ static List* simplify_or_arguments( static List* simplify_and_arguments( List* args, eval_const_expressions_context* context, bool* haveNull, bool* forceFalse); static Node* simplify_boolean_equality(Oid opno, List* args); -static Expr* simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, - List** args_p, bool process_args, bool allow_non_const, eval_const_expressions_context* context); static List* expand_function_arguments(List* args, Oid result_type, HeapTuple func_tuple); static List* reorder_function_arguments(List* args, HeapTuple func_tuple); static List* add_function_defaults(List* args, HeapTuple func_tuple); @@ -3665,7 +3655,7 @@ static Node* simplify_boolean_equality(Oid opno, List* args) * will be done even if simplification of the function call itself is not * possible. */ -static Expr* simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, +Expr* simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List** args_p, bool process_args, bool allow_non_const, eval_const_expressions_context* context) { List* args = *args_p; diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 290e8d05a..67c1097c8 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -42,6 +42,14 @@ typedef struct { List* activeWindows; } WindowLists; +typedef struct { + ParamListInfo boundParams; + PlannerInfo* root; + List* active_fns; + Node* case_val; + bool estimate; +} eval_const_expressions_context; + typedef enum { UNIQUE_CONSTRAINT, NOT_NULL_CONSTRAINT } constraintType; extern Expr* make_opclause( @@ -145,5 +153,7 @@ static inline void ExcludeRownumExpr(ParseState* pstate, Node* expr) extern List* get_quals_lists(Node *jtnode); extern bool isTableofType(Oid typeOid, Oid* base_oid, Oid* indexbyType); +extern Expr* simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, + List** args_p, bool process_args, bool allow_non_const, eval_const_expressions_context* context); #endif /* CLAUSES_H */ diff --git a/src/test/regress/expected/insert_right_ref.out b/src/test/regress/expected/insert_right_ref.out index ea1fe5bb8..ed7c14245 100644 --- a/src/test/regress/expected/insert_right_ref.out +++ b/src/test/regress/expected/insert_right_ref.out @@ -172,5 +172,163 @@ select * from with_var; drop function with_var_func; drop table with_var; +-- test num type +create table num_default_t ( + n serial, + c1 int default 1, + c2 int, + c3 tinyint default 3, + c4 tinyint, + c5 smallint default 5, + c6 smallint, + c7 integer default 7, + c8 integer, + c9 binary_integer default 9, + c10 bigint default 10, + c11 bigint, + c12 boolean default true, + c13 boolean, + c14 numeric default 14., + c15 numeric(10, 3) default 15., + c16 decimal default 16, + c17 decimal(10, 2) default 17, + c18 double precision default 18, + c19 float8, + c20 float default 100 / 10, + c21 float default 20 * (100 + 2) - 3, + c22 float default random(), + c23 float default random() * 100, + c24 float +); +NOTICE: CREATE TABLE will create implicit sequence "num_default_t_n_seq" for serial column "num_default_t.n" +insert into num_default_t values(1); +insert into num_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, + c21, c22, c23, c24); +insert into num_default_t values(3, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, + c21, c22, c23, c20); +insert into num_default_t(n, c23, c24) values(4, default, c23); +select 3, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21 +from num_default_t; + ?column? | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | c16 | c17 | c18 | c19 | c20 | c21 +----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+--------+-----+-------+-----+-----+-----+------ + 3 | 1 | | 3 | | 5 | | 7 | | 9 | 10 | | t | | 14 | 15.000 | 16 | 17.00 | 18 | | 10 | 2037 + 3 | 1 | | 3 | | 5 | | 7 | | 9 | 10 | | t | | 14 | 15.000 | 16 | 17.00 | 18 | | | 2037 + 3 | 1 | | 3 | | 5 | | 7 | | 9 | 10 | | t | | 14 | 15.000 | 16 | 17.00 | 18 | | | 2037 + 3 | 1 | | 3 | | 5 | | 7 | | 9 | 10 | | t | | 14 | 15.000 | 16 | 17.00 | 18 | | 10 | 2037 +(4 rows) + +select (c23 = c24) as equal from num_default_t where n = 4; + equal +------- + t +(1 row) + +select (c22 is null) as c22_is_null, (c23 is null) as c23_is_null from num_default_t where n = 2 or n = 3; + c22_is_null | c23_is_null +-------------+------------- + t | t + t | t +(2 rows) + +select (c22 is not null) as c22_is_not_null, (c23 is not null) as c23_is_not_null from num_default_t where n = 1; + c22_is_not_null | c23_is_not_null +-----------------+----------------- + t | t +(1 row) + +-- test char type +create table char_default_t( + n serial, + c1 char(10) default 'char20', + c2 char(10), + c3 varchar(10) default 'vc3', + c4 varchar(20), + c5 varchar2(10) default 'vc210', + c6 varchar2(20), + c7 nchar(5) default 'c31', + c8 nchar(5), + c9 nvarchar2(5) default 'c33', + c10 nvarchar(5) default 'c34', + c11 varchar(20) default concat('hello', ' world'), + c12 varchar(20) +); +NOTICE: CREATE TABLE will create implicit sequence "char_default_t_n_seq" for serial column "char_default_t.n" +insert into char_default_t values(1); +insert into char_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12); +insert into char_default_t values(3, c1, c2, c3, concat(c3, ' vc4'), c5, c6, c7, c8, c9, c10, default, c11); +select * from char_default_t; + n | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 +---+------------+----+-----+---------+-------+----+-------+----+-----+-----+-------------+------------- + 1 | char20 | | vc3 | | vc210 | | c31 | | c33 | c34 | hello world | + 2 | char20 | | vc3 | | vc210 | | c31 | | c33 | c34 | | + 3 | char20 | | vc3 | vc3 vc4 | vc210 | | c31 | | c33 | c34 | hello world | hello world +(3 rows) + +-- test time type +create table time_default_t( + n serial, + c1 timestamp default '2022-12-12 22:22:22', + c2 timestamp, + c3 date default '2022-12-12', + c4 date, + c5 time default '22:22:22', + c6 date default current_date, + c7 date, + c8 timestamp default current_timestamp, + c9 timestamp, + c10 time default current_time, + c11 time, + c12 time with time zone default current_time, + c13 time +); +NOTICE: CREATE TABLE will create implicit sequence "time_default_t_n_seq" for serial column "time_default_t.n" +insert into time_default_t values(1); +insert into time_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13); +insert into time_default_t values(3, default, c1, default, c3, default, default, c6, + default, c8, default, c10, default, c12); +select n, c1, c2, c3, c4, c5 from time_default_t; + n | c1 | c2 | c3 | c4 | c5 +---+--------------------------+--------------------------+------------+------------+---------- + 1 | Mon Dec 12 22:22:22 2022 | | 12-12-2022 | | 22:22:22 + 2 | Mon Dec 12 22:22:22 2022 | | 12-12-2022 | | 22:22:22 + 3 | Mon Dec 12 22:22:22 2022 | Mon Dec 12 22:22:22 2022 | 12-12-2022 | 12-12-2022 | 22:22:22 +(3 rows) + +select (c6 is not null) as c6_is_not_null, + (c8 is not null) as c8_is_not_null, + (c10 is not null) as c10_is_not_null, + (c12 is not null) as c12_is_not_null +from time_default_t where n = 1 or n = 3; + c6_is_not_null | c8_is_not_null | c10_is_not_null | c12_is_not_null +----------------+----------------+-----------------+----------------- + t | t | t | t + t | t | t | t +(2 rows) + +select (c6 is not null) c6_is_not_null, + (c8 is null) as c8_is_null, + (c10 is null) as c10_is_null, + (c12 is null) as c12_is_null +from time_default_t where n = 2; + c6_is_not_null | c8_is_null | c10_is_null | c12_is_null +----------------+------------+-------------+------------- + t | t | t | t +(1 row) + +select (c1=c2) as c1c2, + (c3=c4) as c3c4, + (c6=c7) as c6c7, + (c8=c9) as c8c9, + (c10=c11) as c10c11, + (c12=c13) as c12c13 +from time_default_t where n = 3; + c1c2 | c3c4 | c6c7 | c8c9 | c10c11 | c12c13 +------+------+------+------+--------+-------- + t | t | t | t | t | t +(1 row) + \c postgres drop database rightref; diff --git a/src/test/regress/sql/insert_right_ref.sql b/src/test/regress/sql/insert_right_ref.sql index b5fddab49..e9308ac9e 100644 --- a/src/test/regress/sql/insert_right_ref.sql +++ b/src/test/regress/sql/insert_right_ref.sql @@ -82,6 +82,121 @@ select * from with_var; drop function with_var_func; drop table with_var; +-- test num type +create table num_default_t ( + n serial, + c1 int default 1, + c2 int, + c3 tinyint default 3, + c4 tinyint, + c5 smallint default 5, + c6 smallint, + c7 integer default 7, + c8 integer, + c9 binary_integer default 9, + c10 bigint default 10, + c11 bigint, + c12 boolean default true, + c13 boolean, + c14 numeric default 14., + c15 numeric(10, 3) default 15., + c16 decimal default 16, + c17 decimal(10, 2) default 17, + c18 double precision default 18, + c19 float8, + c20 float default 100 / 10, + c21 float default 20 * (100 + 2) - 3, + c22 float default random(), + c23 float default random() * 100, + c24 float +); + +insert into num_default_t values(1); +insert into num_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, + c21, c22, c23, c24); +insert into num_default_t values(3, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, + c21, c22, c23, c20); +insert into num_default_t(n, c23, c24) values(4, default, c23); + +select 3, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21 +from num_default_t; + +select (c23 = c24) as equal from num_default_t where n = 4; +select (c22 is null) as c22_is_null, (c23 is null) as c23_is_null from num_default_t where n = 2 or n = 3; +select (c22 is not null) as c22_is_not_null, (c23 is not null) as c23_is_not_null from num_default_t where n = 1; + + +-- test char type +create table char_default_t( + n serial, + c1 char(10) default 'char20', + c2 char(10), + c3 varchar(10) default 'vc3', + c4 varchar(20), + c5 varchar2(10) default 'vc210', + c6 varchar2(20), + c7 nchar(5) default 'c31', + c8 nchar(5), + c9 nvarchar2(5) default 'c33', + c10 nvarchar(5) default 'c34', + c11 varchar(20) default concat('hello', ' world'), + c12 varchar(20) +); + +insert into char_default_t values(1); +insert into char_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12); +insert into char_default_t values(3, c1, c2, c3, concat(c3, ' vc4'), c5, c6, c7, c8, c9, c10, default, c11); + +select * from char_default_t; + +-- test time type +create table time_default_t( + n serial, + c1 timestamp default '2022-12-12 22:22:22', + c2 timestamp, + c3 date default '2022-12-12', + c4 date, + c5 time default '22:22:22', + c6 date default current_date, + c7 date, + c8 timestamp default current_timestamp, + c9 timestamp, + c10 time default current_time, + c11 time, + c12 time with time zone default current_time, + c13 time +); + +insert into time_default_t values(1); +insert into time_default_t values(2, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13); +insert into time_default_t values(3, default, c1, default, c3, default, default, c6, + default, c8, default, c10, default, c12); + +select n, c1, c2, c3, c4, c5 from time_default_t; + +select (c6 is not null) as c6_is_not_null, + (c8 is not null) as c8_is_not_null, + (c10 is not null) as c10_is_not_null, + (c12 is not null) as c12_is_not_null +from time_default_t where n = 1 or n = 3; + +select (c6 is not null) c6_is_not_null, + (c8 is null) as c8_is_null, + (c10 is null) as c10_is_null, + (c12 is null) as c12_is_null +from time_default_t where n = 2; + +select (c1=c2) as c1c2, + (c3=c4) as c3c4, + (c6=c7) as c6c7, + (c8=c9) as c8c9, + (c10=c11) as c10c11, + (c12=c13) as c12c13 +from time_default_t where n = 3; + \c postgres drop database rightref;