forked from huawei/openGauss-server
deep copy procedure arg value
Offering: openGaussDev More detail: deep copy procedure arg value Match-id-dda612d112a2a69b554912340314383a39e71a7c
This commit is contained in:
parent
b93d4de9ed
commit
06c8f2afcf
|
|
@ -258,7 +258,7 @@ static PLpgSQL_rec* copyPLpgsqlRec(PLpgSQL_rec* src);
|
||||||
static PLpgSQL_recfield* copyPLpgsqlRecfield(PLpgSQL_recfield* src);
|
static PLpgSQL_recfield* copyPLpgsqlRecfield(PLpgSQL_recfield* src);
|
||||||
static List* invalid_depend_func_and_packgae(Oid pkgOid);
|
static List* invalid_depend_func_and_packgae(Oid pkgOid);
|
||||||
static void ReportCompileConcurrentError(const char* objName, bool isPackage);
|
static void ReportCompileConcurrentError(const char* objName, bool isPackage);
|
||||||
|
static Datum CopyFcinfoArgValue(Oid typOid, Datum value);
|
||||||
/* ----------
|
/* ----------
|
||||||
* plpgsql_check_line_validity Called by the debugger plugin for
|
* plpgsql_check_line_validity Called by the debugger plugin for
|
||||||
* validating a given linenumber
|
* validating a given linenumber
|
||||||
|
|
@ -1083,12 +1083,12 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, boo
|
||||||
while (argmodes[outArgCnt] == PROARGMODE_OUT) {
|
while (argmodes[outArgCnt] == PROARGMODE_OUT) {
|
||||||
outArgCnt++;
|
outArgCnt++;
|
||||||
}
|
}
|
||||||
var->value = fcinfo->arg[outArgCnt];
|
var->value = CopyFcinfoArgValue(fcinfo->argTypes[outArgCnt], fcinfo->arg[outArgCnt]);
|
||||||
var->isnull = fcinfo->argnull[outArgCnt];
|
var->isnull = fcinfo->argnull[outArgCnt];
|
||||||
var->freeval = false;
|
var->freeval = false;
|
||||||
outArgCnt++;
|
outArgCnt++;
|
||||||
} else {
|
} else {
|
||||||
var->value = fcinfo->arg[i];
|
var->value = CopyFcinfoArgValue(fcinfo->argTypes[i], fcinfo->arg[i]);
|
||||||
var->isnull = fcinfo->argnull[i];
|
var->isnull = fcinfo->argnull[i];
|
||||||
var->freeval = false;
|
var->freeval = false;
|
||||||
}
|
}
|
||||||
|
|
@ -1469,6 +1469,25 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, boo
|
||||||
return estate.retval;
|
return estate.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Datum CopyFcinfoArgValue(Oid typOid, Datum value)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_MULTIPLE_NODES
|
||||||
|
return value;
|
||||||
|
#endif
|
||||||
|
if (!OidIsValid(typOid)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* For centralized database, package value may be in param.
|
||||||
|
* In this case, the value should be copyed, becaues the ref
|
||||||
|
* value may be influenced by procedure.
|
||||||
|
*/
|
||||||
|
bool typByVal = false;
|
||||||
|
int16 typLen;
|
||||||
|
get_typlenbyval(typOid, &typLen, &typByVal);
|
||||||
|
return datumCopy(value, typByVal, typLen);
|
||||||
|
}
|
||||||
|
|
||||||
static void RecordSetGeneratedField(PLpgSQL_rec *recNew)
|
static void RecordSetGeneratedField(PLpgSQL_rec *recNew)
|
||||||
{
|
{
|
||||||
int natts = recNew->tupdesc->natts;
|
int natts = recNew->tupdesc->natts;
|
||||||
|
|
|
||||||
|
|
@ -474,6 +474,7 @@ static void advance_transition_function(
|
||||||
*fcinfo, &(peraggstate->transfn), numTransInputs + 1, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
*fcinfo, &(peraggstate->transfn), numTransInputs + 1, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
||||||
fcinfo->arg[0] = pergroupstate->transValue;
|
fcinfo->arg[0] = pergroupstate->transValue;
|
||||||
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
|
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
|
||||||
|
fcinfo->argTypes[0] = InvalidOid;
|
||||||
fcinfo->isnull = false; /* just in case transfn doesn't set it */
|
fcinfo->isnull = false; /* just in case transfn doesn't set it */
|
||||||
|
|
||||||
Node *origin_fcxt = fcinfo->context;
|
Node *origin_fcxt = fcinfo->context;
|
||||||
|
|
@ -577,6 +578,7 @@ static void advance_collection_function(
|
||||||
InitFunctionCallInfoData(*fcinfo, &(peraggstate->collectfn), 2, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
InitFunctionCallInfoData(*fcinfo, &(peraggstate->collectfn), 2, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
||||||
fcinfo->arg[0] = pergroupstate->collectValue;
|
fcinfo->arg[0] = pergroupstate->collectValue;
|
||||||
fcinfo->argnull[0] = pergroupstate->collectValueIsNull;
|
fcinfo->argnull[0] = pergroupstate->collectValueIsNull;
|
||||||
|
fcinfo->argTypes[0] = InvalidOid;
|
||||||
newVal = FunctionCallInvoke(fcinfo);
|
newVal = FunctionCallInvoke(fcinfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -665,6 +667,7 @@ static void advance_aggregates(AggState* aggstate, AggStatePerGroup pergroup)
|
||||||
for (i = 0; i < numTransInputs; i++) {
|
for (i = 0; i < numTransInputs; i++) {
|
||||||
fcinfo.arg[i + 1] = slot->tts_values[i];
|
fcinfo.arg[i + 1] = slot->tts_values[i];
|
||||||
fcinfo.argnull[i + 1] = slot->tts_isnull[i];
|
fcinfo.argnull[i + 1] = slot->tts_isnull[i];
|
||||||
|
fcinfo.argTypes[i + 1] = InvalidOid;
|
||||||
}
|
}
|
||||||
for (setno = 0; setno < numGroupingSets; setno++) {
|
for (setno = 0; setno < numGroupingSets; setno++) {
|
||||||
AggStatePerGroup pergroupstate = &pergroup[aggno + (setno * numAggs)];
|
AggStatePerGroup pergroupstate = &pergroup[aggno + (setno * numAggs)];
|
||||||
|
|
@ -896,6 +899,7 @@ static void finalize_aggregate(AggState* aggstate, AggStatePerAgg peraggstate, A
|
||||||
foreach (lc, peraggstate->aggrefstate->aggdirectargs) {
|
foreach (lc, peraggstate->aggrefstate->aggdirectargs) {
|
||||||
fcinfo.arg[args_pos] =
|
fcinfo.arg[args_pos] =
|
||||||
ExecEvalExpr((ExprState*)lfirst(lc), aggstate->ss.ps.ps_ExprContext, &fcinfo.argnull[args_pos], NULL);
|
ExecEvalExpr((ExprState*)lfirst(lc), aggstate->ss.ps.ps_ExprContext, &fcinfo.argnull[args_pos], NULL);
|
||||||
|
fcinfo.argTypes[args_pos] = ((ExprState*)lfirst(lc))->resultType;
|
||||||
if (anynull == true || fcinfo.argnull[args_pos] == true)
|
if (anynull == true || fcinfo.argnull[args_pos] == true)
|
||||||
anynull = true;
|
anynull = true;
|
||||||
else
|
else
|
||||||
|
|
@ -928,6 +932,7 @@ static void finalize_aggregate(AggState* aggstate, AggStatePerAgg peraggstate, A
|
||||||
fcinfo, &(peraggstate->finalfn), numFinalArgs, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
fcinfo, &(peraggstate->finalfn), numFinalArgs, peraggstate->aggCollation, (Node*)aggstate, NULL);
|
||||||
fcinfo.arg[0] = pergroupstate->transValue;
|
fcinfo.arg[0] = pergroupstate->transValue;
|
||||||
fcinfo.argnull[0] = pergroupstate->transValueIsNull;
|
fcinfo.argnull[0] = pergroupstate->transValueIsNull;
|
||||||
|
fcinfo.argTypes[0] = InvalidOid;
|
||||||
if (anynull == true || pergroupstate->transValueIsNull == true)
|
if (anynull == true || pergroupstate->transValueIsNull == true)
|
||||||
anynull = true;
|
anynull = true;
|
||||||
else
|
else
|
||||||
|
|
@ -936,6 +941,7 @@ static void finalize_aggregate(AggState* aggstate, AggStatePerAgg peraggstate, A
|
||||||
while (args_pos < numFinalArgs) {
|
while (args_pos < numFinalArgs) {
|
||||||
fcinfo.arg[args_pos] = (Datum)0;
|
fcinfo.arg[args_pos] = (Datum)0;
|
||||||
fcinfo.argnull[args_pos] = true;
|
fcinfo.argnull[args_pos] = true;
|
||||||
|
fcinfo.argTypes[args_pos] = InvalidOid;
|
||||||
args_pos++;
|
args_pos++;
|
||||||
anynull = true;
|
anynull = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ static void advance_windowaggregate(
|
||||||
ExprState* arg_state = (ExprState*)lfirst(arg);
|
ExprState* arg_state = (ExprState*)lfirst(arg);
|
||||||
|
|
||||||
fcinfo->arg[i] = ExecEvalExpr(arg_state, econtext, &fcinfo->argnull[i], NULL);
|
fcinfo->arg[i] = ExecEvalExpr(arg_state, econtext, &fcinfo->argnull[i], NULL);
|
||||||
|
fcinfo->argTypes[i] = arg_state->resultType;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +177,7 @@ static void advance_windowaggregate(
|
||||||
*fcinfo, &(peraggstate->transfn), num_arguments + 1, perfuncstate->winCollation, (Node*)winstate, NULL);
|
*fcinfo, &(peraggstate->transfn), num_arguments + 1, perfuncstate->winCollation, (Node*)winstate, NULL);
|
||||||
fcinfo->arg[0] = peraggstate->transValue;
|
fcinfo->arg[0] = peraggstate->transValue;
|
||||||
fcinfo->argnull[0] = peraggstate->transValueIsNull;
|
fcinfo->argnull[0] = peraggstate->transValueIsNull;
|
||||||
|
fcinfo->argTypes[0] = InvalidOid;
|
||||||
new_val = FunctionCallInvoke(fcinfo);
|
new_val = FunctionCallInvoke(fcinfo);
|
||||||
/*
|
/*
|
||||||
* If pass-by-ref datatype, must copy the new value into aggcontext and
|
* If pass-by-ref datatype, must copy the new value into aggcontext and
|
||||||
|
|
@ -216,6 +218,7 @@ static void finalize_windowaggregate(WindowAggState* winstate, WindowStatePerFun
|
||||||
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1, perfuncstate->winCollation, (Node*)winstate, NULL);
|
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1, perfuncstate->winCollation, (Node*)winstate, NULL);
|
||||||
fcinfo.arg[0] = peraggstate->transValue;
|
fcinfo.arg[0] = peraggstate->transValue;
|
||||||
fcinfo.argnull[0] = peraggstate->transValueIsNull;
|
fcinfo.argnull[0] = peraggstate->transValueIsNull;
|
||||||
|
fcinfo.argTypes[0] = InvalidOid;
|
||||||
if (fcinfo.flinfo->fn_strict && peraggstate->transValueIsNull) {
|
if (fcinfo.flinfo->fn_strict && peraggstate->transValueIsNull) {
|
||||||
/* don't call a strict function with NULL inputs */
|
/* don't call a strict function with NULL inputs */
|
||||||
*result = (Datum)0;
|
*result = (Datum)0;
|
||||||
|
|
|
||||||
|
|
@ -2873,6 +2873,68 @@ drop procedure pp1;
|
||||||
drop package pck1;
|
drop package pck1;
|
||||||
NOTICE: drop cascades to function pkg_val_2.p1()
|
NOTICE: drop cascades to function pkg_val_2.p1()
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
-- test package variable as in param
|
||||||
|
create type o1 as (a int, b varchar2);
|
||||||
|
create or replace package pck1 as
|
||||||
|
va varchar2;
|
||||||
|
vb varchar2 := 'vb';
|
||||||
|
vc o1;
|
||||||
|
procedure p1;
|
||||||
|
end pck1;
|
||||||
|
/
|
||||||
|
create or replace package body pck1 as
|
||||||
|
procedure p1 as
|
||||||
|
begin
|
||||||
|
va := 'hahahah';
|
||||||
|
vc := (1,'cccc');
|
||||||
|
end;
|
||||||
|
end pck1;
|
||||||
|
/
|
||||||
|
create table testlog(a int);
|
||||||
|
create or replace procedure insertlog() is
|
||||||
|
PRAGMA AUTONOMOUS_TRANSACTION;
|
||||||
|
begin
|
||||||
|
insert into testlog values(1);
|
||||||
|
pck1.va := 'bbbbbbb';
|
||||||
|
pck1.vc := (123,'ayayayayay');
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
raise notice 'sqlerrm:%',sqlerrm;
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
create or replace procedure p1(va in varchar2, vb in varchar2, vc in o1) is
|
||||||
|
begin
|
||||||
|
raise info 'before auto: %,%', vb,vc;
|
||||||
|
insertlog();
|
||||||
|
raise info 'after auto: %,%', vb,vc;
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
raise notice 'sqlerrm:%',sqlerrm;
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
declare
|
||||||
|
begin
|
||||||
|
pck1.p1();
|
||||||
|
p1(150,pck1.va,pck1.vc);
|
||||||
|
raise info 'after p1: %,%', pck1.va,pck1.vc;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
INFO: before auto: hahahah,(1,cccc)
|
||||||
|
CONTEXT: SQL statement "CALL p1(150,pck1.va,pck1.vc)"
|
||||||
|
PL/pgSQL function inline_code_block line 4 at PERFORM
|
||||||
|
INFO: after auto: hahahah,(1,cccc)
|
||||||
|
CONTEXT: SQL statement "CALL p1(150,pck1.va,pck1.vc)"
|
||||||
|
PL/pgSQL function inline_code_block line 4 at PERFORM
|
||||||
|
INFO: after p1: bbbbbbb,(123,ayayayayay)
|
||||||
|
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure insertlog;
|
||||||
|
drop package pck1;
|
||||||
|
NOTICE: drop cascades to function pkg_val_2.p1()
|
||||||
|
drop table testlog;
|
||||||
|
drop type o1;
|
||||||
-- clean
|
-- clean
|
||||||
DROP SCHEMA IF EXISTS pkg_val_1 CASCADE;
|
DROP SCHEMA IF EXISTS pkg_val_1 CASCADE;
|
||||||
DROP SCHEMA IF EXISTS pkg_val_2 CASCADE;
|
DROP SCHEMA IF EXISTS pkg_val_2 CASCADE;
|
||||||
|
|
|
||||||
|
|
@ -2238,6 +2238,61 @@ drop procedure pp1;
|
||||||
drop package pck1;
|
drop package pck1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
-- test package variable as in param
|
||||||
|
create type o1 as (a int, b varchar2);
|
||||||
|
create or replace package pck1 as
|
||||||
|
va varchar2;
|
||||||
|
vb varchar2 := 'vb';
|
||||||
|
vc o1;
|
||||||
|
procedure p1;
|
||||||
|
end pck1;
|
||||||
|
/
|
||||||
|
create or replace package body pck1 as
|
||||||
|
procedure p1 as
|
||||||
|
begin
|
||||||
|
va := 'hahahah';
|
||||||
|
vc := (1,'cccc');
|
||||||
|
end;
|
||||||
|
end pck1;
|
||||||
|
/
|
||||||
|
create table testlog(a int);
|
||||||
|
create or replace procedure insertlog() is
|
||||||
|
PRAGMA AUTONOMOUS_TRANSACTION;
|
||||||
|
begin
|
||||||
|
insert into testlog values(1);
|
||||||
|
pck1.va := 'bbbbbbb';
|
||||||
|
pck1.vc := (123,'ayayayayay');
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
raise notice 'sqlerrm:%',sqlerrm;
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
create or replace procedure p1(va in varchar2, vb in varchar2, vc in o1) is
|
||||||
|
begin
|
||||||
|
raise info 'before auto: %,%', vb,vc;
|
||||||
|
insertlog();
|
||||||
|
raise info 'after auto: %,%', vb,vc;
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
raise notice 'sqlerrm:%',sqlerrm;
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
declare
|
||||||
|
begin
|
||||||
|
pck1.p1();
|
||||||
|
p1(150,pck1.va,pck1.vc);
|
||||||
|
raise info 'after p1: %,%', pck1.va,pck1.vc;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure insertlog;
|
||||||
|
drop package pck1;
|
||||||
|
drop table testlog;
|
||||||
|
drop type o1;
|
||||||
|
|
||||||
-- clean
|
-- clean
|
||||||
DROP SCHEMA IF EXISTS pkg_val_1 CASCADE;
|
DROP SCHEMA IF EXISTS pkg_val_1 CASCADE;
|
||||||
DROP SCHEMA IF EXISTS pkg_val_2 CASCADE;
|
DROP SCHEMA IF EXISTS pkg_val_2 CASCADE;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue