**FREE /TITLE GETOBJUR - Get users of an object //-------------------------------------------------------------------- // Note: // The QSYS2.OBJECT_LOCK_INFO SQL service is used, so this code // probably won't run prior to OS 7.2. //-------------------------------------------------------------------- // Given an object and type, this program finds all jobs that have // locks on the object. It returns a message suitable for sending // to the system operator and/or a file, QTEMP/GETOBJUP, which // could be used to send messages to all interactive users of the // object, or for some other use. Or the jobname can be copied and // pasted into a command, e.g. wrkjob 110080/LENNONS/QPAD142626. // This program is called from CL program GETOBJUC. // It uses the QSYS2.OBJECT_LOCK_INFO SQL view. // Message looks like this: // QIWS/QCUSTCDT *FILE is in use by 110088/LENNONS/QPAD142626. // Or this: // QIWS/QCUSTCDT *FILE is in use by 191174/LENNONS/QPAD160408, // 191550/LENNONS/CUSTLST, 191551/LENNONS/INV_UPD, 191552/LENNONS/DAILYORD // plus 1 more. //-------------------------------------------------------------------- // Compile: CRTBNDRPG PGM(GETOBJUR) SRCFILE(...) DBGVIEW(*LIST) //-------------------------------------------------------------------- // 12/00/97 LENNON Original Writing // 07/--/2021 Converted to **FREE and Linear module. // There are SQL services now that can provide similar // infomations, but as far as I know there is no SQL // interface to QWCLOBJL. And there certainly was not in // 1997. This code probably performs better than existing // SQL interfaces. For most use cases performance may not // be a consideration. // 08/--/2021 Converted to use QSYS2.OBJECT_LOCK_INFO and to create the // GETOBJUP file with SQL. // 09/17/2021 - Fixed member logic by uppercasing CASE values // - Added input parms to GETOBJUP output file. //-------------------------------------------------------------------- ctl-opt debug option(*nodebugio: *srcstmt) dftactgrp(*no) actgrp(*caller) bnddir('UTIL_BND':'SQL_BND') main(Main); //=== Prototypes ===================================================== /include copy_mbrs,Srv_Msg_P /include copy_mbrs,Srv_SQL_P // Gets job type entry for this job. // Returns: JobType has the job type. I=interactive, B=batch, etc. dcl-pr GetJobType extpgm('GETJOBTR'); *n char(26); // JobName26 *n char(1); // JobType end-pr; //=== Program Parameters ============================================= // Input Parameters // 1) pObject is object name (10c) + object library (10c) // 2) pObjType is *FILE, *DTAARA, etc., standard OS/400 type // 3) pObjMem is the member for files, or *NONE if just want users // of the file. // 4) pMsgYN is *YES to create a message. // 5) pFileYN is *YES if file GETOBJUP is to be created in QTEMP // Output Parameter // PMsgFld is where the message gets created. //=== Global Definitions ============================================= dcl-s JobName28 char(28); // like '580065/JOBNM/USER'' dcl-c SQLSuccess '00000'; dcl-c SQLNoData '02000'; dcl-c SQLNoMoreData '02000'; dcl-c SQLProcWarning '01548'; dcl-c SQLFileNotFound '42704'; //==================================================================== dcl-proc Main ; //=== Misc Field Definitions ===================================== dcl-s NumJobs packed(5); dcl-c MaxJobs const(4); //Maximum jobs for detailed reporting. // If you increase MaxJobs, increase the message parameter by 30 bytes // for each additional job. dcl-s JobName26 char(26); // is name(10) User(10) number(6) dcl-ds JobSQLDS; // Output data for GETOBJUP JobName char(10); JobUser char(10); JobNum char(6); JobType char(1); JobNM28 char(28); JobOBJLIB CHAR(10); JobOBJNAME CHAR(10); JobOBJTYPE CHAR(10); JobOBJMBR CHAR(10); end-ds; dcl-s theLibrary char(10); dcl-s theObject char(10); dcl-s j int(10); // --------------------------------------------------------- dcl-pi *n extpgm('GETOBJUR'); pObject char(20); pObjType char(10); pObjMem char(10); pMsgYN char(4); pMsgFld char(200); pFileYN char(4); end-pi; //=== Code starts here =========================================== exec sql set option datfmt=*iso, closqlcsr=*endmod, commit=*none; // === Initialize requested outputs =============================== if pMsgYN='*YES'; clear pMsgFld; endif; if pFileYN='*YES'; exec sql drop table qtemp.GETOBJUP; if SQLSTATE <> SQLSuccess and SQLSTATE <> SQLFileNotFound; SQLProblem('Delete GETOBJUP'); endif; exec sql declare global temporary table GETOBJUP ( OUJOBNAME char(10), OUJOBUSER char(10), OUJOBNUM char(6), OUJOBTYPE char(1), OUJOBNAME28 CHAR(28), OUOBJLIB CHAR(10), OUOBJNAME CHAR(10), OUOBJTYPE CHAR(10), OUOBJMBR CHAR(10) ); if SQLSTATE <> SQLSuccess; SQLProblem('Declare global tempory table GETOBJUP'); endif; endif; // Split Library/Object theObject = %subst(pObject:1:10); theLibrary = %subst(pObject:11:10); // Put parms in output file data structure JobOBJLIB = theLibrary; JobOBJNAME = theObject; JobOBJTYPE = pObjType; JobOBJMBR = pObjMem; // === Find the locks ============================================ exec sql declare Lock_Cursor cursor for select distinct JOB_NAME from QSYS2.OBJECT_LOCK_INFO where SYSTEM_OBJECT_SCHEMA = :thelibrary and SYSTEM_OBJECT_NAME = :theobject and OBJECT_TYPE = :pobjtype and ifnull(SYSTEM_TABLE_MEMBER,' ') = case when :pobjtype = '*FILE' and :pobjmem <> '*ALL' then :pobjmem else ' ' END order by JOB_NAME ; exec sql open Lock_Cursor ; if SQLSTT <> SQLSuccess; SQLProblem('open Lock_Cursor'); endif; // Loop through the cursor, building requested outputs fetchNext(); dow SQLSTT <> SQLNoData; NumJobs += 1; if pFileYN='*YES'; // Build JobName26, parm for GetJobType // JobName28 is like '580065/USER/JOBNAME' // 1234567890123456789 JobNum = %subst(JobName28 :1 :6); // Num Always 6 j = %scan('/' : JobName28 :8); // find 2nd '/' (j=12) JobUser= %subst(JobName28 :8 : j-8); // User (lgth j-8 = 4) JobName = %subst(JobName28: j+1); // Rest is Job Name JobName26= JobName + JobUser + JobNum; GetJobType(JobName26: JobType); exsr WriteRec; endif; if pMsgYN='*YES'; exsr BldMsg; endif; fetchNext(); enddo; // === End of Program ============================================ if pMsgYN='*YES'; select; when NumJobs >= 1 and NumJobs <=MaxJobs; pMsgfld=%trimr(pMsgFld) + '.'; when NumJobs > MaxJobs; pMsgfld=%trimr(pMsgFld) + ' plus ' + %trim(%editc(NumJobs-MaxJobs:'J')) + ' more.'; other; endsl; endif; *inlr=*on; // === BldMsg ==================================================== // Adds current job to the message until MaxJobs have been added. begsr BldMsg; select; when NumJobs=1; pMsgFld= %trimr(%subst(pObject:11:10)) +'/' + %trimr(%subst(pObject:1:10)) + ' ' + %trimr(pObjType) + ' is in use by ' + JobName28; when NumJobs >= 2 and NumJobs <=MaxJobs; pMsgFld=%trimr(pMsgfld) + ', ' + JobName28; endsl; endsr; // === WriteRec ================================================== // Builds and writes a record to the file GETOBJUP begsr WriteRec; JobNM28 = JobName28; exec sql insert into qtemp.GETOBJUP values(:JobSQLDS); if SQLSTT <> SQLSuccess; sqlProblem('Insert into GETOBJUP'); endif; endsr; end-proc; // === fetchNext ===================================================== dcl-proc fetchNext; exec sql fetch next from Lock_Cursor into :JobName28; if SQLSTT <> SQLSuccess and SQLSTT <> SQLNOData and SQLSTT <> SQLProcWarning; SQLProblem('fetchNext'); endif; end-proc;