Examples
Consider the PL/SQL function SUM present in the package RP_CUSTOM_PKG
. To execute the SUM
function in the RPASCE application batch, first upload RP_CUSTOM_PKG
as described in the section Uploading Custom PL/SQL Packages. The PL/SQL function SUM
is declared as below in the package RP_CUSTOM_PKG
.
function SUM (lhsMeas IN VARCHAR2, rhsMeas1 IN VARCHAR2, rhsMeas2 IN VARCHAR2) return number;
Here is a sample definition of the SUM
function that adds 2 measures and writes the result to a third
measure. Note that the measure lhsMeas
is an IN
type argument although the function SUM
updates it. The measure lhsMeas
must be marked as a customer managed measure as described
in the Measure Properties subsection of the RPASCE Configuration Tools Changes section.
FUNCTION sum (
lhsmeas IN VARCHAR2,
rhsmeas1 IN VARCHAR2,
rhsmeas2 IN VARCHAR2
) RETURN NUMBER IS
-- EXPR 1: lhsMeas = rhsMeas2 + rhsMeas1
na_ut_lhsmeas BINARY_DOUBLE := cell_dbl(lhsmeas, NULL);
na_ut_rhsmeas1 BINARY_DOUBLE := cell_dbl(rhsmeas1, NULL);
na_ut_rhsmeas2 BINARY_DOUBLE := cell_dbl(rhsmeas2, NULL);
lhsfactgroup VARCHAR2(4000);
rhs1factgroup VARCHAR2(4000);
rhs2factgroup VARCHAR2(4000);
lhsfacttable VARCHAR2(4000);
rhs1facttable VARCHAR2(4000);
rhs2facttable VARCHAR2(4000);
stmt VARCHAR2(8000);
BEGIN
rp_g_common_pkg.clear_facts(varchar2_table(lhsmeas));
SELECT
fact_group
INTO lhsfactgroup
FROM
rp_g_fact_info_md
WHERE
fact_name = lhsmeas;
SELECT
fact_group
INTO rhs1factgroup
FROM
rp_g_fact_info_md
WHERE
fact_name = rhsmeas1;
SELECT
fact_group
INTO rhs2factgroup
FROM
rp_g_fact_info_md
WHERE
fact_name = rhsmeas2;
lhsfacttable := 'rp_g_'
|| lhsfactgroup
|| '_ft';
rhs1facttable := 'rp_g_'
|| rhs1factgroup
|| '_ft';
rhs2facttable := 'rp_g_'
|| rhs2factgroup
|| '_ft';
na_ut_lhsmeas := ( na_ut_rhsmeas2 + na_ut_rhsmeas1 );
stmt := 'MERGE INTO '
|| lhsfacttable
|| ' lhs
USING (
SELECT
( coalesce(rhsft01.partition_id, rhsft02.partition_id) ) AS partition_id,
( coalesce(rhsft01.dept_id, rhsft02.dept_id) ) AS dept_id,
( coalesce(rhsft01.stor_id, rhsft02.stor_id) ) AS stor_id,
( ( coalesce(rhsft02.'
|| rhsmeas2
|| ', '
|| na_ut_rhsmeas2
|| ') + coalesce(rhsft01.'
|| rhsmeas1
|| ', '
|| na_ut_rhsmeas1
|| ') ) ) AS '
|| lhsmeas
|| '
FROM
(
SELECT
partition_id,
dept_id,
stor_id,
'
|| rhsmeas1
|| '
FROM
'
|| rhs1facttable
|| '
) rhsft01
FULL OUTER JOIN (
SELECT
partition_id,
dept_id,
stor_id,
'
|| rhsmeas2
|| '
FROM
'
|| rhs2facttable
|| '
) rhsft02 ON rhsft01.partition_id = rhsft02.partition_id
AND rhsft01.dept_id = rhsft02.dept_id
AND rhsft01.stor_id = rhsft02.stor_id
)
rhs_final ON ( lhs.partition_id = rhs_final.partition_id
AND lhs.dept_id = rhs_final.dept_id
AND lhs.stor_id = rhs_final.stor_id )
WHEN MATCHED THEN UPDATE
SET lhs.'
|| lhsmeas
|| '= nullif(rhs_final.'
|| lhsmeas
|| ', '
|| na_ut_lhsmeas
|| ') DELETE
WHERE
rhs_final.'
|| lhsmeas
|| ' = '
|| na_ut_lhsmeas
|| '
WHEN NOT MATCHED THEN
INSERT (
lhs.partition_id,
lhs.dept_id,
lhs.stor_id,
lhs.'
|| lhsmeas
|| ' )
VALUES
( rhs_final.partition_id,
rhs_final.dept_id,
rhs_final.stor_id,
nullif(rhs_final.'
|| lhsmeas
|| ', '
|| na_ut_lhsmeas
|| ') )
WHERE
rhs_final.'
|| lhsmeas
|| ' != '
|| na_ut_lhsmeas;
dbms_output.put_line(stmt);
EXECUTE IMMEDIATE stmt;
COMMIT;
RETURN 0;
END sum;
Now to execute this SUM
function from the application batch, add the rule below to application configuration
as described in the Rules and Expressions subsection of RPASCE Configuration Tools Changes section. Add the rule group containing the rule to the batch
control files as described in the section RPASCE Batch Control File Changes. Patch the application with the updated configuration and batch control
files.
drdvsrcti<-execplsql("RP_CUSTOM_PKG","sum",drdvsrctt, adhdlcratet, add2locopnd)
Here all 3 measures are placeholder scalar string measures that will point to the actual real measures that are being summed.
In this example, the input scalar measures are mapped as follows:
-
drdvsrctt: lpwpsellthrmn - dept_stor - customer managed (LHS measure)
Label: Wp Sell Thru R % Min Threshold
-
adhdlcratet: lpwprtnmn - dept_stor (RHS1)
Label: Wp Returns R % Min Threshold
-
add2locopnd: lpwprtnmx - dept_stor (RHS2)
Label: Wp Returns R % Max Threshold
Alternately, the rule could have been configured as below. However, that would mean that it is not possible to change the
input measures as part of the batch. It will need a patch to update the input measures to the SUM
procedure.
Note:
The measures are in quotes as they are passed to PL/SQL as string constants. If the quotes are missing, then RPASCE will throw an error indicating that it is not possible to invokeexecplsql
using non-scalar measures.
drdvsrcti<-execplsql("RP_CUSTOM_PKG","sum",'lpwpsellthrmn' , 'lpwprtnmn' ,'lpwprtnmx' )
Execute this rule group through batch and build a measure analysis workbook with the involved measures. It can then be
verified that the SUM
evaluated correctly.
If measure lhsMeas
is not specified as a customer-managed measure in the application configuration,
then the error below will be thrown when execplsql
is evaluated.
<E OCI_ERROR - (1031):
<E SQL Sid 'rpas_iw_conn' ORA-01031: insufficient privileges
The following examples demonstrate execplsql
and how a special expression can invoke PL/SQL with
a variable number and type of input arguments.
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_procedure1","dvsn", true, 1, 1)
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_procedure2","dvsn", 1123.5813, 23, -1)
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_function1","dvsn", true, 1)
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_function2","dvsn", 1)
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_function2",strscalar1, intscalar02)
intscalar01<-execplsql("RP_CUSTOM_PKG","custom_procedure3","dvsn", datescalar2, 1, 1)
The PL/SQL counterparts are defined, through very simple demonstration code, in the example custom package below.
rp_custom_pdg.pkb
create or replace package body RP_CUSTOM_PKG is
procedure custom_procedure1(arg1 in varchar2, arg2 in CHAR, arg3 in number, ret out number )
is
begin
ret:=23;
end custom_procedure1;
procedure custom_procedure2(arg1 in varchar2, arg2 in BINARY_DOUBLE, arg3 in number, ret out number )
is
begin
ret:=23;
end custom_procedure2;
procedure custom_procedure3(arg1 in varchar2, arg2 in BINARY_DOUBLE, arg3 in timestamp, ret out number )
is
begin
dbms_output.put_line('arg3: ' || arg3);
ret:=23;
end custom_procedure3;
function custom_function1(arg1 in varchar2, arg2 in CHAR, arg3 in number) return number
is
ret integer;
begin
ret:=23;
return ret;
end custom_function1;
function custom_function2(arg1 in varchar2, arg3 in number) return number
is
ret number;
begin
ret:=23;
return ret;
end custom_function2;
function SUM
(lhsMeas IN VARCHAR2,
rhsMeas1 IN VARCHAR2,
rhsMeas2 IN VARCHAR2) return number
is
-- EXPR 1: lhsMeas = rhsMeas2 + rhsMeas1
na_ut_lhsMeas BINARY_DOUBLE := cell_dbl(lhsMeas, NULL);
na_ut_rhsMeas1 BINARY_DOUBLE := cell_dbl(rhsMeas1, NULL);
na_ut_rhsMeas2 BINARY_DOUBLE := cell_dbl(rhsMeas2, NULL);
lhsFactGroup varchar2(4000);
rhs1FactGroup varchar2(4000);
rhs2FactGroup varchar2(4000);
lhsFactTable varchar2(4000);
rhs1FactTable varchar2(4000);
rhs2FactTable varchar2(4000);
stmt varchar2(8000);
BEGIN
rp_g_common_pkg.clear_facts(varchar2_table(lhsMeas));
select fact_group into lhsFactGroup from RP_G_FACT_INFO_MD where FACT_NAME = lhsMeas;
select fact_group into rhs1FactGroup from RP_G_FACT_INFO_MD where FACT_NAME = rhsMeas1;
select fact_group into rhs2FactGroup from RP_G_FACT_INFO_MD where FACT_NAME = rhsMeas2;
lhsFactTable := 'rp_g_' || lhsFactGroup || '_ft';
rhs1FactTable := 'rp_g_' || rhs1FactGroup || '_ft';
rhs2FactTable := 'rp_g_' || rhs2FactGroup || '_ft';
na_ut_lhsMeas := ( na_ut_rhsMeas2 + na_ut_rhsMeas1 );
-- UPDATE rp_g_fact_info_md
-- SET
-- table_na =
-- CASE lower(fact_name)
-- WHEN 'b' THEN
-- to_char(na_ut_lhsMeas)
-- END
-- WHERE
-- lower(fact_name) IN ( lhsMeas );
stmt := 'MERGE INTO ' || lhsFactTable || ' lhs
USING (
SELECT
( coalesce(rhsft01.partition_id, rhsft02.partition_id) ) AS partition_id,
( coalesce(rhsft01.dept_id, rhsft02.dept_id) ) AS dept_id,
( coalesce(rhsft01.stor_id, rhsft02.stor_id) ) AS stor_id,
( ( coalesce(rhsft02.' || rhsMeas2 || ', ' || na_ut_rhsMeas2 || ') + coalesce(rhsft01.' || rhsMeas1 || ', ' || na_ut_rhsMeas1 || ') ) ) AS '|| lhsMeas||'
FROM
(
SELECT
partition_id,
dept_id,
stor_id,
'|| rhsMeas1 ||'
FROM
' || rhs1FactTable || '
) rhsft01
FULL OUTER JOIN (
SELECT
partition_id,
dept_id,
stor_id,
' || rhsMeas2 || '
FROM
' || rhs2FactTable || '
) rhsft02 ON rhsft01.partition_id = rhsft02.partition_id
AND rhsft01.dept_id = rhsft02.dept_id
AND rhsft01.stor_id = rhsft02.stor_id
)
rhs_final ON ( lhs.partition_id = rhs_final.partition_id
AND lhs.dept_id = rhs_final.dept_id
AND lhs.stor_id = rhs_final.stor_id )
WHEN MATCHED THEN UPDATE
SET lhs.' || lhsMeas || '= nullif(rhs_final.' || lhsMeas || ', ' || na_ut_lhsMeas || ') DELETE
WHERE
rhs_final.' || lhsMeas || ' = ' || na_ut_lhsMeas || '
WHEN NOT MATCHED THEN
INSERT (
lhs.partition_id,
lhs.dept_id,
lhs.stor_id,
lhs.' || lhsMeas || ' )
VALUES
( rhs_final.partition_id,
rhs_final.dept_id,
rhs_final.stor_id,
nullif(rhs_final.' || lhsMeas || ', ' || na_ut_lhsMeas || ') )
WHERE
rhs_final.' || lhsMeas || ' != ' || na_ut_lhsMeas ;
DBMS_OUTPUT.PUT_LINE (stmt);
execute immediate stmt;
commit;
return 0;
END SUM;
end RP_CUSTOM_PKG;
rp_custom_pkg.pks
create or replace package RP_CUSTOM_PKG is
procedure custom_procedure1(arg1 in varchar2, arg2 in CHAR, arg3 in number, ret out number );
procedure custom_procedure2(arg1 in varchar2, arg2 in BINARY_DOUBLE, arg3 in number, ret out number );
procedure custom_procedure3(arg1 in varchar2, arg2 in BINARY_DOUBLE, arg3 in timestamp, ret out number );
function custom_function1(arg1 in varchar2, arg2 in CHAR, arg3 in number) return number ;
function custom_function2(arg1 in varchar2, arg3 in number) return number;
function SUM (lhsMeas IN VARCHAR2, rhsMeas1 IN VARCHAR2, rhsMeas2 IN VARCHAR2) return number;
end RP_CUSTOM_PKG;