Transcript EGL - IBM

®
IBM Software Group
EGL and IMS Support
A short, high-level introduction to the language and tooling features
For more information, please contact Jon Sayles: [email protected]
© 2006 IBM Corporation
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
Last update: 12/04/2007
2
EGL - IMS Run-Time Architecture
DL/I
Database
MSG Queue
EGL
Catcher
Program
EGL
COBOLGEN
Program
Web Services
WAS - AIX
Last update: 12/04/2007
3
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
Last update: 12/04/2007
4
DLISegment Record
 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
Last update: 12/04/2007
5
PSBRecord
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
6
Last update: 12/04/2007
DL/I Data Access Calls
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
with #dli{ GU
COURSE*D (COURSE# = :COURSE.COURSE#)
OFFERING (LOCATION = :OFFERING.LOCATION
& CITY = :MYDBPRG_WS.MYCITY)
7
Last 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) } ;
Last update: 12/04/2007
8
#dli directive
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
Last update: 12/04/2007
9
DLILIB – Option for customized DL/I Calls
 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);
if (CustomerRec not handleIOError)
// do error processing end
10
Last update: 12/04/2007
DL/I Program - Properties
Program FLSCOMP 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", "", ""]
}
}
Last update: 12/04/2007
11
DL/I Error Handling
 Can “roll your own” – or leverage built-in coding standards:
if (myRec is noRecordFound)
…
Last update: 12/04/2007
12
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
Last update: 12/04/2007
13
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) };
Last update: 12/04/2007
14
Examples – Path calls and implicit SSAs
EGL I/O statement with dependent segments
get myCustomer, myLocation, myOrder; //Path get
//This statement generates 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;
replace myOrder with #dli{
REPL
STSCCST*N
STSCLOC*N
STPCORD };
Last update: 12/04/2007
15
//Path get
Examples – Read all database segments
EGL I/O statement with dependent segments
myHistory 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
Last update: 12/04/2007
16
Last update: 12/04/2007
17
®
IBM Software Group
Getting Started with EGL
© 2006 IBM Corporation