Initial commit
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
@@ -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
|
||||
|
||||

|
||||
@@ -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
|
||||
)
|
||||
);
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user