!2584 【问题】解决自定义变量运算过程中的core问题

Merge pull request !2584 from yuhuanhuan/demand_set
This commit is contained in:
opengauss-bot
2022-12-08 12:02:58 +00:00
committed by Gitee
6 changed files with 105 additions and 3 deletions

View File

@ -1567,16 +1567,27 @@ static Node* transformUserVar(UserVar *uservar)
GucUserParamsEntry *entry = (GucUserParamsEntry *)hash_search(u_sess->utils_cxt.set_user_params_htab,
uservar->name, HASH_FIND, &found);
if (!found) {
/* return a null const */
Const *nullValue = makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false);
return (Node *)nullValue;
}
entry = (GucUserParamsEntry *)hash_search(u_sess->utils_cxt.set_user_params_htab, uservar->name, HASH_ENTER, &found);
if (entry == NULL) {
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to create user_defined entry due to out of memory")));
}
UserVar *result = makeNode(UserVar);
Const *con = (Const *)copyObject(entry->value);
result->name = uservar->name;
result->value = (Expr *)copyObject(entry->value);
result->value = (Expr *)con;
USE_MEMORY_CONTEXT(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB));
/* if uservar is parsed, set to true */
entry->value = (Const *)copyObject(con);
entry->isParse = true;
return (Node *)result;
}

View File

@ -12975,11 +12975,13 @@ void check_variable_value_info(const char* var_name, const Expr* var_expr)
if (found) {
entry->value = (Const *)copyObject((Const *)(var_expr));
entry->isParse = false;
} else {
errno_t errval = strncpy_s(entry->name, sizeof(entry->name), var_name, sizeof(entry->name) - 1);
securec_check_errval(errval, , LOG);
entry->value = (Const *)copyObject((Const *)(var_expr));
entry->isParse = false;
}
}

View File

@ -1083,7 +1083,22 @@ static Datum ExecEvalConst(ExprState* exprstate, ExprContext* econtext, bool* is
GucUserParamsEntry *entry = (GucUserParamsEntry *)hash_search(u_sess->utils_cxt.set_user_params_htab, uservar->name, HASH_FIND, &found);
/* if not found, return a null const */
con = found ? entry->value : makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false);
if (found) {
if (entry->isParse) {
con = (Const *)uservar->value;
} else {
Node *node = coerce_type(NULL, (Node *)entry->value, entry->value->consttype, ((Const *)uservar->value)->consttype,
-1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
node = eval_const_expression_value(NULL, node, NULL);
if (nodeTag(node) != T_Const) {
ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION),
errmsg("The value of a user_defined variable must be convertible to a constant.")));
}
con = (Const *)node;
}
} else {
con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false);
}
} else if (IsA(exprstate->expr, SetVariableExpr)) {
SetVariableExpr* setvar = (SetVariableExpr*)transformSetVariableExpr((SetVariableExpr*)exprstate->expr);
con = (Const*)setvar->value;

View File

@ -191,6 +191,7 @@ typedef struct {
typedef struct {
char name[NAMEDATALEN]; /* user-defined name */
Const *value;
bool isParse;
} GucUserParamsEntry;
#define GUC_QUALIFIER_SEPARATOR '.'

View File

@ -532,6 +532,28 @@ select @v1;
set @ v1:=10;
select @v1:=10;
--DTS
\c test_set
set @v := 10;
select @v + 666::numeric(10, 2), @v + 20::float;
set @v = @v + 666::numeric(10, 2);
select @v;
set @v1 := 10, @v2 := 13.3;
drop table if exists test_pro;
create table test_pro(f1 int, f2 float);
create or replace procedure pro_insert()
as
begin
insert into test_pro values(@v1 + 666::numeric(10, 2), @v2 + 20::float);
end;
/
call pro_insert();
select * from test_pro;
set @v1 := 11, @v2 := 14.3;
call pro_insert();
select * from test_pro;
\c test_set
show enable_set_variable_b_format;
set enable_set_variable_b_format = off;

View File

@ -1125,6 +1125,57 @@ LINE 1: set @ v1:=10;
^
select @v1:=10;
ERROR: user_defined variables cannot be set, such as @var_name := expr is not supported.
--DTS
\c test_set
set @v := 10;
select @v + 666::numeric(10, 2), @v + 20::float;
?column? | ?column?
----------+----------
676.00 | 30
(1 row)
set @v = @v + 666::numeric(10, 2);
select @v;
@v
-----
676
(1 row)
set @v1 := 10, @v2 := 13.3;
drop table if exists test_pro;
create table test_pro(f1 int, f2 float);
create or replace procedure pro_insert()
as
begin
insert into test_pro values(@v1 + 666::numeric(10, 2), @v2 + 20::float);
end;
/
call pro_insert();
pro_insert
------------
(1 row)
select * from test_pro;
f1 | f2
-----+------
676 | 33.3
(1 row)
set @v1 := 11, @v2 := 14.3;
call pro_insert();
pro_insert
------------
(1 row)
select * from test_pro;
f1 | f2
-----+------
676 | 33.3
677 | 34.3
(2 rows)
\c test_set
show enable_set_variable_b_format;
enable_set_variable_b_format