!2584 【问题】解决自定义变量运算过程中的core问题
Merge pull request !2584 from yuhuanhuan/demand_set
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -191,6 +191,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
char name[NAMEDATALEN]; /* user-defined name */
|
||||
Const *value;
|
||||
bool isParse;
|
||||
} GucUserParamsEntry;
|
||||
|
||||
#define GUC_QUALIFIER_SEPARATOR '.'
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user