Initial commit

This commit is contained in:
SJLennon
2023-06-27 12:44:31 -04:00
parent 22158fd3d9
commit af1f785000
5 changed files with 194 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

+36
View File
@@ -0,0 +1,36 @@
# SQL Procedure to find Program Usage recursively using DSPPGMREF
Given a program (or any of the objects that DSPPGMREF handles), the PGM_REFS procedure will find all the obects that the program uses, and then recursively find all that objects that they use, and so on, to an essentally unlimited depth.
This is the product of my experimentation with PL/SQL. It may be short on error handling, and it doesn't do any validity checking on the paremeters.
If you have more experience than me, please feel free to suggest better coding techniques.
So far I have not found a decent manual or turorial. If you have any I'd like to know.
My primary source was trial and error, with help
from these articles by Ted Holt in IT Jungle:
[Ted HolT Article 1](https://www.itjungle.com/2017/06/12/guru-error-handling-sql-pl-part-1/) and
[Ted Holt Article 2](https://www.itjungle.com/2017/10/16/guru-error-handling-sql-pl-part-2/)
and browsing [Scott Forstie Gists on Github](https://gist.github.com/forstie
)
In no way does this replace a real cross reference utilily, such as Hawkeye
or X-Analysis. If you don't have one, this might be somewhat useful.
## pgm_refs_Tbl.sql
This is the DDL to create the file that the procedure builds.
Change the library and then run this first.
## pgm_refs.sql
This is the code to create the PGM_REFS procedure. The library in which the REFS file is build needs to be changed to suit your environment.
## pgm_refs_test.SQL
These are some samples of calling the procedure to test it. I used iACS Run SQL scripts. You could also call it in a CL program using the RUNSQLSTM command.
## Sample Output File Contents
![Sample ](Images/Sample1.png)
+22
View File
@@ -0,0 +1,22 @@
-- Table created by the PGM_REFS SQL procedure
-- Change LENNONSB to your library name to suit and make
-- a similar change in PGM_REFS.
DROP TABLE LENNONSB.REFS;
create or replace TABLE LENNONSB.REFS (
DEPTH integer
,CALLER_LIBRARY VarCHAR(10) NOT NULL
,CALLER_NAME VarCHAR(10) NOT NULL
,CALLER_TYPE VarCHAR(10) NOT NULL
,CALLER_TEXT Varchar(30) NOT NULL
,USES_LIBRARY VarCHAR(10) NOT NULL
,USES_NAME VarCHAR(10) NOT NULL
,USES_TYPE VarCHAR(10) NOT NULL
,CONSTRAINT LENNONSB.refs_pk PRIMARY KEY (
CALLER_LIBRARY
,CALLER_NAME
,CALLER_TYPE
,USES_LIBRARY
,USES_NAME
,USES_TYPE
)
);
+117
View File
@@ -0,0 +1,117 @@
-- Procedure to run DPSPGMREF, then run DSPPGMREF on each of its objects
-- by calling itself recursively.
-- Result is a file named REFS containing all the objects that
-- DSPPGMREF knows about an object, to an essentially unlimited depth.
CREATE OR REPLACE PROCEDURE PGM_REFS (
IN p_INLIB varCHAR(10)
,IN p_INPGM varCHAR(10)
,IN p_INTYPE varCHAR(10) default '*PGM'
,in p_Depth integer default(0)
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SET OPTION dbgview = *source, commit = *none
begin
-- Define DSPPGMREF library and file names
declare WrkLib varchar(10) default 'QTEMP';
declare WrkFileOS varchar(20) default '/WRK' ;
declare WrkFileSQL varchar(20) default '.WRK';
declare sqlstate char(5);
declare my_sqlstate char(5);
declare no_more_data char(5) default '02000';
declare duplicate_key char(5) default '23505';
declare Cmd varchar(1024);
declare ref_cursor_txt varchar(512) default
'select WHLIB, WHPNAM, WHTEXT, WHLNAM, WHFNAM, WHOTYP
from ' ;
-- Our cross ref fields for the REFS file
declare CALLER_LIBRARY varchar(10);
declare CALLER_NAME varchar(10);
declare CALLER_TYPE varchar(10);
declare CALLER_TEXT varchar(30);
declare USES_LIBRARY varchar(10);
declare USES_NAME varchar(10);
declare USES_TYPE varchar(10);
declare USES_TEXT varchar(30);
declare duplicate_object condition for sqlstate '23505';
declare ref_cursor cursor for ref_cursor_stmt;
declare continue handler for duplicate_object
begin
set my_sqlstate = duplicate_key;
end;
-- Build pgm refs work file from DSPPGMREF command.
set WrkFileOS = WrkLib
concat trim(WrkFileOS)
concat trim(char(p_Depth));
set Cmd ='DSPPGMREF PGM('
concat trim(p_INLIB)
concat '/' concat trim(p_INPGM) concat ')'
concat ' OBJTYPE(' concat p_INTYPE CONCAT ')'
concat ' OUTPUT(*OUTFILE)'
concat ' OUTFILE(' concat WrkFileOS concat ')'
;
CALL QSYS2.QCMDEXC (Cmd);
-- Open cursor over the outfile from DSPPGMREF
set WrkFileSQL = WrkLib
concat trim(WrkFileSQL)
concat trim(char(p_Depth));
set ref_cursor_txt = ref_cursor_txt concat WrkFileSQL;
prepare ref_cursor_stmt from ref_cursor_txt;
open ref_cursor;
-- Read through the records from DSPPGMREF
Refs_Loop: loop
fetch from ref_cursor into
CALLER_LIBRARY
,CALLER_NAME
,CALLER_TEXT
,USES_LIBRARY
,USES_NAME
,USES_TYPE
;
if sqlstate = no_more_data then
leave Refs_Loop;
end if;
-- <<<< Change this table library >>>>>
insert into lennonsb.refs values (
p_Depth
,CALLER_LIBRARY
,CALLER_NAME
,p_INTYPE
,CALLER_TEXT
,USES_LIBRARY
,USES_NAME
,USES_TYPE
);
-- If used object already exists don't add again
if my_sqlstate = duplicate_key then
set my_sqlstate = ' ';
iterate Refs_Loop;
end if;
-- Don't expand IBM stuff further
if substr(USES_NAME, 1, 1) = 'Q' then
iterate Refs_Loop;
end if;
-- No further expansion if DSPPGMREF doesn't handle object
if USES_TYPE not in
( '*PGM', '*SRVPGM', '*MODULE', '*QRYDFN', '*SQLPKG') then
iterate Refs_Loop;
end if;
-- Recursively expand this object
call pgm_refs(
USES_LIBRARY, USES_NAME, trim(USES_TYPE), p_Depth+1);
end loop;
close ref_cursor;
set Cmd = 'DLTF FILE(' concat WrkFileOS concat ')';
CALL QSYS2.QCMDEXC (Cmd);
-- drop table WrkFileSQL;
end;
+19
View File
@@ -0,0 +1,19 @@
-- Depth field starts at 0, type of *PGM assumed
call lennons1.pgm_refs('LENNONS1', 'MTNCUSTR');
call lennons1.pgm_refs(p_inlib => 'LENNONS1', p_inpgm => 'MTNCUSTR');
-- Depth field starts at 6789, an arbitrary number
call lennons1.pgm_refs('LENNONS1', 'MTNCUSTR','*PGM', 6789);
call lennons1.pgm_refs(p_depth => 6789, p_inlib => 'LENNONS1', p_inpgm => 'MTNCUSTR');
-- Start with a *MODULE
call lennons1.pgm_refs(p_inlib => 'LENNONSB', p_inpgm => 'ART300', p_INTYPE => '*MODULE');
-- Start with a *SRVPGMMODULE
call lennons1.pgm_refs(p_inlib => 'LENNONSB', p_inpgm => 'FVAT', p_INTYPE => '*SRVPGM');
-- List the output file of objects used
select * from lennonsb.refs
order by DEPTH, CALLER_LIBRARY, CALLER_NAME, CALLER_TYPE,
USES_LIBRARY, USES_NAME, USES_TYPE;