Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/pl/plisql/src/expected/plisql_nested_subproc.out
Original file line number Diff line number Diff line change
Expand Up @@ -4078,3 +4078,68 @@ SELECT test_func_1005_multi(10) FROM dual;
(1 row)

DROP FUNCTION test_func_1005_multi;
CREATE TABLE test_subproc_recfield(id integer, name varchar2(256));
CREATE OR REPLACE FUNCTION trig_subproc_recfield1() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
FUNCTION get_id() RETURN integer IS
BEGIN
RETURN v_id;
END;
BEGIN
RAISE INFO 'id: %', get_id();
RETURN new;
END;
$$ LANGUAGE plisql;
/
CREATE TRIGGER trig_subproc_recfield1_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield1();
INSERT INTO test_subproc_recfield VALUES(42, 'hello');
INFO: id: 42
DROP TRIGGER trig_subproc_recfield1_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield1();
CREATE OR REPLACE FUNCTION trig_subproc_recfield2() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
v_result integer := 0;
PROCEDURE accumulate(p_val integer) IS
BEGIN
v_result := v_result + p_val;
END;
BEGIN
accumulate(v_id);
RAISE INFO 'result: %', v_result;
RETURN new;
END;
$$ LANGUAGE plisql;
/
CREATE TRIGGER trig_subproc_recfield2_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield2();
INSERT INTO test_subproc_recfield VALUES(10, 'world');
INFO: result: 10
DROP TRIGGER trig_subproc_recfield2_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield2();
CREATE OR REPLACE FUNCTION trig_subproc_recfield3() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
v_name varchar2(256) := new.name;
FUNCTION summary() RETURN text IS
BEGIN
RETURN v_id::text || ':' || v_name;
END;
BEGIN
RAISE INFO '%', summary();
RETURN new;
END;
$$ LANGUAGE plisql;
/
CREATE TRIGGER trig_subproc_recfield3_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield3();
INSERT INTO test_subproc_recfield VALUES(5, 'test');
INFO: 5:test
DROP TRIGGER trig_subproc_recfield3_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield3();
DROP TABLE test_subproc_recfield;
25 changes: 25 additions & 0 deletions src/pl/plisql/src/pl_subproc_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,24 @@ plisql_init_subprocfunc_globalvar(PLiSQL_execstate * estate, FunctionCallInfo fc
if (estate->datums[i]->dtype == PLISQL_DTYPE_ROW)
continue;

/*
* Skip RECFIELD datums. A RECFIELD carries no independent value;
* it is purely field-reference metadata (recparentno + fieldname).
* Such datums can appear in the outer-scope range as a compile-time
* side-effect: when scanning a DEFAULT expression that references a
* record field (e.g. "var1 integer := new.id"), plisql_build_recfield
* is called by the lexer before lastassignvardno is recorded, placing
* the RECFIELD at an index below lastassignvardno. The parent record
* (e.g. NEW/OLD) is propagated separately, so there is nothing to do
* here.
*/
if (estate->datums[i]->dtype == PLISQL_DTYPE_RECFIELD)
{
/* Parent record must precede its RECFIELD in the datum array */
Assert(((PLiSQL_recfield *) estate->datums[i])->recparentno < i);
continue;
}

/* Ignore datums that don't require assignment */
if (is_subprocfunc_argnum(pfunc, i))
continue;
Expand Down Expand Up @@ -1328,6 +1346,13 @@ plisql_assign_out_subprocfunc_globalvar(PLiSQL_execstate * estate,
if (estate->datums[i]->dtype == PLISQL_DTYPE_ROW)
continue;

/* See comment in plisql_init_subprocfunc_globalvar */
if (estate->datums[i]->dtype == PLISQL_DTYPE_RECFIELD)
{
Assert(((PLiSQL_recfield *) estate->datums[i])->recparentno < i);
continue;
}

/* Ignore datums that don't require assignment */
if (is_subprocfunc_argnum(pfunc, i))
continue;
Expand Down
74 changes: 74 additions & 0 deletions src/pl/plisql/src/sql/plisql_nested_subproc.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3890,3 +3890,77 @@ END;
SELECT test_func_1005_multi(10) FROM dual;

DROP FUNCTION test_func_1005_multi;
CREATE TABLE test_subproc_recfield(id integer, name varchar2(256));

CREATE OR REPLACE FUNCTION trig_subproc_recfield1() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
FUNCTION get_id() RETURN integer IS
BEGIN
RETURN v_id;
END;
BEGIN
RAISE INFO 'id: %', get_id();
RETURN new;
END;
$$ LANGUAGE plisql;
/

CREATE TRIGGER trig_subproc_recfield1_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield1();

INSERT INTO test_subproc_recfield VALUES(42, 'hello');

DROP TRIGGER trig_subproc_recfield1_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield1();

CREATE OR REPLACE FUNCTION trig_subproc_recfield2() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
v_result integer := 0;
PROCEDURE accumulate(p_val integer) IS
BEGIN
v_result := v_result + p_val;
END;
BEGIN
accumulate(v_id);
RAISE INFO 'result: %', v_result;
RETURN new;
END;
$$ LANGUAGE plisql;
/

CREATE TRIGGER trig_subproc_recfield2_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield2();

INSERT INTO test_subproc_recfield VALUES(10, 'world');

DROP TRIGGER trig_subproc_recfield2_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield2();

CREATE OR REPLACE FUNCTION trig_subproc_recfield3() RETURNS TRIGGER AS $$
DECLARE
v_id integer := new.id;
v_name varchar2(256) := new.name;
FUNCTION summary() RETURN text IS
BEGIN
RETURN v_id::text || ':' || v_name;
END;
BEGIN
RAISE INFO '%', summary();
RETURN new;
END;
$$ LANGUAGE plisql;
/

CREATE TRIGGER trig_subproc_recfield3_trig
AFTER INSERT ON test_subproc_recfield
FOR EACH ROW EXECUTE PROCEDURE trig_subproc_recfield3();

INSERT INTO test_subproc_recfield VALUES(5, 'test');

DROP TRIGGER trig_subproc_recfield3_trig ON test_subproc_recfield;
DROP FUNCTION trig_subproc_recfield3();
DROP TABLE test_subproc_recfield;