Upload
mansour-jalil
View
43
Download
1
Embed Size (px)
DESCRIPTION
EGL and IMS Support. A short, high-level introduction to the language and tooling features For more information, please contact Jon Sayles: [email protected]. From 10,000 Feet. Support for: IMS TM Formatted and un-formatted 3270 screens Alternate IO-PCB IMS BMP - PowerPoint PPT Presentation
Citation preview
®
IBM Software Group
© 2006 IBM Corporation
EGL and IMS Support
A short, high-level introduction to the language and tooling features
For more information, please contact Jon Sayles: [email protected]
2Last update: 12/04/2007
From 10,000 Feet
Support for: IMS TM
Formatted and un-formatted 3270 screens Alternate IO-PCB
IMS BMP zOS – IMS Batch (DL/I programs) DL/I Database
All databases and access methods supported HDAM/HIDAM Secondary Index Logical Relationships GSAM
Complete DL/I language support Different levels of abstraction – use of consistent vocabulary Ability to support custom/complex requirements through #dli{
Special records that provide abstracted and simplified coding – AND learning IMS
3Last update: 12/04/2007
EGL - IMS Run-Time Architecture
zSeries – IMS/VS – DB2zSeries – IMS/VS – DB2
EGLCOBOLGEN
Program
EGLCatcherProgram
MSG Queue
DL/IDL/IDatabaseDatabase
WAS - AIXWAS - AIX
Web ServicesWeb Services
4Last update: 12/04/2007
From 10,000 Feet – Development Architecture
Support for: TUI/MFS Interface – tooling and form editors available to produce Pagehandlers – generated to Java Services – generated to Java IMS Programs – generated to COBOL
Buildfile entries for lots of things Build Server – COBUCL
Call: ELAISVN EGL “catcher program” that is called by IMS Connect Transaction:
ELAISVN Is defined to AIB – with aliases for all user program PSB Scans the iopcb message queue for requests for said PSBs Gets scheduled Handles data mapping and Linkage Parms:
– Unformatted 3270 data streams (IMS Message data, passed to your called program)
Invokes custom IMS/VS programs (your generated EGL code – or Native COBOL !) Handles passing returned data/parms to caller client programs
– Pages/Services/MFS
5Last update: 12/04/2007
Record subtypes are used to associate meta data with a data type definition
Record CustomerRecordPart type DLISegment
{ segmentName="STSCCST", keyItem="customerNo" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key
10 customerName char(25) { dliFieldName = "STUCCNM" };
10 customerAddr1 char(25){ dliFieldName = "STQCCA1" };
10 customerAddr2 char(25){ dliFieldName = "STQCCA2" };
10 customerAddr3 char(25){ dliFieldName = "STQCCA3" };
end
You define records to match segments in DL/I database
The above record provides developers with the following kinds of coding/productivity constructs:Move in_cust_no to customerNo;
Get CustomerRecord;
DLISegment Record
6Last update: 12/04/2007
EGL provides predefined records for the I/O PCB, alternate PCB, database PCB, and GSAM PCB structures.
Record CustomerPSB type PSBRecord { defaultPSBName="STBICLG" }
// three PCBs required for CBLTDLI on IMS
{ @PCB { pcbType = TP } };
elaalt ALT_PCBRecord { @PCB { pcbType = TP } };
elaexp ALT_PCBRecord { @PCB { pcbType = TP } };
// database PCB defining four segment levels
customerPCB DB_PCBRecord
{ @PCB { pcbType = DB, pcbName = "STDCDBL", hierarchy = [
@Relationship
{ segmentRecord = "CustomerRecordPart" },
@Relationship
{ segmentRecord = "LocationRecordPart", parentRecord = "CustomerRecordPart" },
@Relationship
{ segmentRecord = "OrderRecordPart", parentRecord = "LocationRecordPart" },
@Relationship
{ segmentRecord = "ItemRecordPart", parentRecord = "OrderRecordPart" },
@Relationship
{ segmentRecord = "CreditRecordPart", parentRecord = "CustomerRecordPart" },
@Relationship
{ segmentRecord = "HistoryRecordPart", parentRecord = "CustomerRecordPart" }
]}};
PSBRecord
7Last update: 12/04/2007
EGL provides different layers of abstraction for your DL/I programming
Function FLSCOMP_MAIN()
// 1. Implicit DL/I -- retrieves the segment based on the key and DLISegent properties
get STORESEG;
// 2. Explicit DL/I -- with specific SSA for just the root segment – over-rides DLISegment
// use : to indicate a host variable (not a DLI term), but like SQL
get STORESEG usingPCB psb.STORE_dbPCB
with #dli{GU STORESEG(STORE# = :inputStore & COMPFLAG = "Y") } ;
//3. Custom DL/I -- multiple segments and the D (path call) command code
get COURSE, STUDENT usingPCB psb.COURSE_dbPCB get COURSE, STUDENT usingPCB psb.COURSE_dbPCB
with #dli{ GUwith #dli{ GU
COURSE*D (COURSE# = :COURSE.COURSE#) COURSE*D (COURSE# = :COURSE.COURSE#)
OFFERING (LOCATION = :OFFERING.LOCATIONOFFERING (LOCATION = :OFFERING.LOCATION
& CITY = :MYDBPRG_WS.MYCITY) & CITY = :MYDBPRG_WS.MYCITY)
STUDENT (EMPNO = :STUDENT.EMPNO)STUDENT (EMPNO = :STUDENT.EMPNO)
} ;} ;
Note for the above 3 types of IMS db access EGL parses the IMS calls, ensuring that all operands are space-filled to the appropriate length, upper-case, etc.
You can also code native DL/I using DLILIB (system function library)
DL/I Data Access Calls
8Last update: 12/04/2007
DL/I Implicit and Explicit Calls
Calls generated from: 1. DLISegment record, 2. Your coding
Function FLSCOMP_MAIN()
// 1. Implicit DL/I -- retrieves the segment based on the key and DLISegent properties
CustRec CustomerRecordPart;
customerNo = inputCustNo; //Value obtained from Service or web page
get CustRec;
// 2. Explicit DL/I - over-rides DLISegment
get CustRec usingPCB psb.STORE_dbPCB
with #dli{
GU CustRec
(customerName >= :inputName &
customerAddr3 = :addr1) } ;
9Last update: 12/04/2007
Lets you modify the default DL/I calls that EGL generates from I/O keywords.
get myLocation with #dli{ GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)
};
Can use this directive when:
- Need to add DL/I command code
- Retrieve a segment not based on key-field value
- Doing “skip sequential” processing
#dli directive
10Last update: 12/04/2007
DLILib.AIBTDLI() uses the AIBTDLI interface to invoke a DL/I function directly.
DLILib.AIBTDLI()( func CHAR(4) in, pcbName STRING in parms... ANY)
Example:
Record CustomerPSBRecordPart type PSBRecord { defaultPSBName="STBICLG" } // database PCB customerPCB DB_PCBRecord { @PCB { pcbType = DB, pcbName = "STDCDBL", hierarchy = [ @Relationship { segmentRecord = "CustomerRecordPart" }, ...]}}; end
mypsb CustomerPSBRecordPart; //variable definition of PSB
Define I/O area…define and format your SSAs. Issue the DL/I FLD call as follows:
DLILib.AIBTDLI("FLD", "STDCDBL", myIOArea, mySSA1, ... mySSAn); DLILib.AIBTDLI("FLD", "STDCDBL", myIOArea, mySSA1, ... mySSAn);
if (CustomerRec not handleIOError) // do error processing end
DLILIB – Option for customized DL/I Calls
11Last update: 12/04/2007
DL/I Program - Properties
Program FLSCOMPFLSCOMP type basicProgram (inputStore bigint, outputCompFlag char(1), outputDate char(8)) { // whatever other properties you generally use @DLI { psb = "psb", // name of variable that defines the psbRecord
callInterface = DLICallInterfaceKind.AIBTDLI //, this is the default;
// be sure IMS PSB is set up for AIBTDLI // if not, can specify separate CBLTDLI pcbs
//// You can pass the entire psb on a call into this program// psbParm = "psbData"//// Or, you pass individual pcbs on a call into this program// pcbParms = ["iopcb", "ELAALT", "", "STORE_dbPCB", "", ""] } }
12Last update: 12/04/2007
DL/I Error Handling
Can “roll your own” – or leverage built-in coding standards:
if (myRec is noRecordFound)
…
13Last update: 12/04/2007
Examples – Searching within a parent segment
Retrieve the items for a particular order. You can use the following to retrieve the order:
get myOrder with #dli {
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STSOCORD (STQCODN = :myOrder.orderDateno) };
Use the following to retrieve the line segments within the order:
get next inParent myItem;
while (myItem not noRecordFound)
// process the current item get next
14Last update: 12/04/2007
Examples – Searching with a non-key field
Search on the creditBalance field (STFCSBL) in the credit segment (STSCSTA). 1. Define a variable of type decimal(12,2) (for example, ″targetBalance″)
2. Write a get next statement for the myCrStatus record.
3. Add a #dli directive to the line, modifying the default code.
4. Add a qualified SSA that looks for a segment where the amount in the creditBalance field is greater than targetBalance.
5. Include a path command code (*D) to retrieve the customer segment (STSCCST) that corresponds to the credit segment.
TargetBalance decimal(12,2);
targetBalance = 10,000.00; //or any input variable value
get next myCustomer,myCrStatus with #dli{
GU STSCCST*D STSCSTA (STFCSBL >= :targetBalance) };
15Last update: 12/04/2007
Examples – Path calls and implicit SSAs
EGL I/O statement with dependent segments
get myCustomer, myLocation, myOrder; get myCustomer, myLocation, myOrder; //Path get//This statement generatesgenerates the following DL/I pseudocode:
GU STSCCST*D (STQCCNO = :myCustomer.customerNo) STSCLOC*D (STQCLNO = :myLocation.locationNo) STPCORD (STQCDDN = :myOrder.orderDateNo)
Note that if you use the D command code on a get...forUpdate statement, the subsequent replace statement affects every segment retrieved. You can prevent replacement of a selected segment by specifying an explicit N command code in the SSA for the replace keyword, as in the following example, which replaces only the location and order segments:
get myCustomer, myLocation, myOrder forUpdate; get myCustomer, myLocation, myOrder forUpdate; //Path get
replace myOrder with #dli{ replace myOrder with #dli{
REPL REPL STSCCST*N STSCCST*N
STSCLOC*N STSCLOC*N
STPCORD }; STPCORD };
16Last update: 12/04/2007
Examples – Read all database segments
EGL I/O statement with dependent segmentsmyHistory HistoryRecord;
redefCustomer CustomerRecord {redefines=myHistory};
redefLocation LocationRecord {redefines=myHistory};
...
//read next segment, whatever type it is, into history record
while (myHistory not EOF)
get next myHistory with #dli{ GN };
//so what type was it?
case (DLIVar.segmentName)
when "STSCCST"
// it was a customer
when "STSCLOC"
// it was a location
... end
end