当默认值节点为FuncExpr时,若可以转换为Const,则取Const为默认值

This commit is contained in:
laishenghao
2022-12-05 11:38:22 +08:00
parent b3e8d8ff5a
commit fecf7634ac
5 changed files with 306 additions and 14 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;