TechTip - Analyze Your Programs and Applications, Part II - System Administration - IT Infrastructure 3
TechTip - Analyze Your Programs and Applications, Part II - System Administration - IT Infrastructure 3
TechTip - Analyze Your Programs and Applications, Part II - System Administration - IT Infrastructure 3
<> '' ) select upd.* from upd exception join cpl on odsrcm = mlname
Now you'll want the list of sources modi ed but not recompiled:
with cpl as (
SELECT ODOBNM, ODSRCM , case when odsrcc = '' then ' ' else trim(char(
ODSRCC+ 19)) concat ODSRCD concat '-' concat odsrct end cpldate ,
ODOBTX FROM jpltools.objs WHERE odsrcm <> '' and odsrcc <> ''
), upd as (
SELECT MLNAME, case when MLCHGc = '' then ' ' else trim(char(
MLCHGC+ 19)) concat MLCHGD concat '-' concat MLCHGt end
Upddate,MLMTXT FROM jpltools.mbrlist WHERE MLCHGc <> ''
cpldate concat case when upddate = cpldate then '' else ' was updated
' concat upddate end "Compiled_date"
, case when mlmtxt = odobtx then ' ' concat odobtx else '>> '
concat odobtx concat ' changed to ' concat mlmtxt end "Text"
from cpl join upd on odsrcm = mlname and (cpldate <> upddate
Figure 11: These are the sources modi ed but not recompiled.
Remember that these analyses are based on the fact that program and source code members
have the same name. It is common, but not 100 percent accurate.
Program Cross-Reference
I'm gaining momentum, and after getting so much information from two system commands,
other questions have quickly come to mind:
How can we tell if a program or le is no longer used? Explore DSPPGMREF. Obviously, we cannot
answer this question if the program name is determined dynamically in the application.
Here's a more di cult question: A program that should not be used remains called in some
programs (last-used date is recent, days-used count continues to grow…). How can we get an
impact analysis of deleting this program? The answer is again provided by SQL—speci cally by
the recursive SQL on the DSPPGMREF out le.
In the same way and by writing the recursion in the opposite direction, I have obtained for a given
program a list of all programs and les it uses. SQL recursion has been available since V5R4.
OUTFILE(JPLTOOLS/PGMREF)
Why a "simple version"? Because there's a complex version. Indeed, DSPPGMREF allows you to
nd cross-references—not only PGM, but also SQLPKG, SRVPGM, MODULE, and QRYDFN. Yes,
but with several minor problems.
First problem: The structure of the DSPPGMREF out le does not give the type of the object
scanned. This information is actually provided by the column WHSPKG:
WHSPKG Type
P *PGM
S *SQLPKG
V *SRVPGM
M *MODULE
Q *QRYDFN
This forces us to, at least, require that the transformation be able to make joins with the
DSPOBJD le:
alter table jpltools.pgmref add column whptyp char (10 ) not null with
default ;
Second problem: Variable names are exposed (dynamically called programs). We may want to
ignore them. And the modules overlap program references, so they are not useful.
Third problem: DSPPGMREF provided a list of all formats, especially for DSPF. My analysis of
cross-references does not descend to the le format level; this information is then simply useless
duplicates.
Fourth problem: Depending on whether the target application uses the library list or the quali ed
objects, joins will, or will not, integrate the objects library.
Fifth problem: WHLNAM and WHFNAM columns for the library and the referenced object are 11
characters instead of 10, causing some errors in the joins on WHLIB and WHPNAM
Embedding SQL transformation (needed to correct these problems) in the recursive SQL would
make the SQL statement not understandable. There are two methods to deal with this problem:
Either build a view on jpltools/pgmref, or do an insert into another table. I chose the insert.
whlib caller_lib
, whpnam caller
, cast (case
, whotyp called_type
The Caller_key and Called_key columns are used to simplify the writing of recursive joins.
It is likely that you already have a scheduled batch job that runs DSPPGMREF. I suggest that you
either compile the three samples of SQL above by using CRTQMQRY and then add these three
with a repackaging STRQMQRY in the same batch, or copy the three samples of SQL above in a
source member and then add one repackaging RUNSQLSTM in the same batch.
, level, called_key) as (
select caller,
as varchar(1000) ) title_caller
, called
as varchar(21) ) title_called
, 1 level
, called_key
from jpltools.root
-- where caller='MYPGM'
union all
select
cascade.caller
concat cascade.title_called
, child.called
concat trim(child.called)
as varchar(21) ) title_called
, level + 1
, child.called_key
--
Now, the same recursion, but the other way. This analysis allows you to, for example, search to
nd whether a le or program is still present that should have disappeared, understand the
impact of a change, or prepare a test plan.
, level, caller_key) as (
select caller,
, called
, 1 level
, caller_key
from jpltools.root
-- where whpnam='MYPGM'
union all
select
child.caller
, cascade.called
, level + 1
, child.caller_key