Note that the implicit and explicit DL/I code uses a powerful pseudo-DL/I syntax with some differences from actual DL/I code. For more information, see #dli directive.
If you are not familiar with DL/I, see Basic DL/I concepts.
The next table lists the EGL keywords that you can use to access a DL/I database. Included in this table are sample DL/I calls that each keyword might generate. When you code an EGL add statement, for example, you generate a DL/I ISRT call. You can preview an unformatted version of the DL/I calls that EGL will generate by placing your cursor in a line of code that contains a keyword and right-clicking the line. From the popup menu, select DLI Statement > View.
You can also code DL/I calls directly, using the with #dli{ statement } syntax. This syntax allows you to further specify how your program should access the database, as is necessary if the default DL/I calls that EGL generates from I/O keywords are not sufficient.
The following table shows the EGL I/O statements that support DL/I databases, and some examples of COBOL code those EGL statements might generate. The examples assume you have used the @DLI complex property to set your call interface to CBLTDLI. You can just as easily use the default AIBTDLI interface, in which case the COBOL will contain an AIB mask instead of a PCB mask. The AIB mask allows the program to specify a PCB by name rather than address. For details on the @DLI property, see @DLI.
I/O keyword/purpose | Example DL/I call |
---|---|
add Places a record of type DLISegment into a DL/I database; or (if you use a dynamic array of DLISegment records), places a set of records under a single parent segment, based on the content of each element of the array. |
CALL 'CBLTDLI' USING EZEDLI-ISRT EZEPCB-MASK01 EZEORSEG-IO-AREA EZECUST-QUALIFIED-SSA EZELOC-QUALIFIED-SSA EZEORSSA-EZEUNQ-UNQUALIFIED-SSA |
delete Deletes a segment from a database. You must first use a get...forUpdate, get next...forUpdate, or get next inParent...forUpdate statement (generating a DL/I GHU, GHN, or GHNP statement) to locate and hold the record. |
CALL 'CBLTDLI' USING EZEDLI-DLET EZEPCB-MASK01 EZEORSEG-IO-AREA |
get Reads a unique segment from a database; or (if you use a dynamic array of DLISegment records), reads successive segments into successive elements in the array. If you use get to read successive records into an array, the COBOL program will loop through a series of GN calls following the initial GU. |
CALL 'CBLTDLI' USING EZEDLI-GU EZEPCB-MASK01 EZEORSEG-IO-AREA EZECUST-QUALIFIED-SSA EZELOC-QUALIFIED-SSA |
get...forUpdate Reads and holds a unique segment from a database; or (if you use a dynamic array of DLISegment records), reads successive segments into successive elements in the array and holds them (by issuing a series of GHN calls after the initial GHU). |
CALL 'CBLTDLI' USING EZEDLI-GHU EZEPCB-MASK01 EZEORSEG-IO-AREA EZECUST-QUALIFIED-SSA EZELOC-QUALIFIED-SSA |
get next Reads the next segment based on the current position in the database. |
CALL 'CBLTDLI' USING EZEDLI-GN EZEPCB-MASK01 EZEORSEG-IO-AREA EZEUNQ-UNQUALIFIED-SSA |
get next...forUpdate Reads and holds the next segment based on the current position in the database. |
CALL 'CBLTDLI' USING EZEDLI-GHN EZEPCB-MASK01 EZEORSEG-IO-AREA EZEUNQ-UNQUALIFIED-SSA |
get next inParent Reads the next segment that has the same parent segment, based on the current position in the database. |
CALL 'CBLTDLI' USING EZEDLI-GNP EZEPCB-MASK01 EZEORSEG-IO-AREA EZEUNQ-UNQUALIFIED-SSA |
get next inParent...forUpdate Reads and holds the next segment that has the same parent segment, based on the current position in the database. |
CALL 'CBLTDLI' USING EZEDLI-GHNP EZEPCB-MASK01 EZEORSEG-IO-AREA EZEUNQ-UNQUALIFIED-SSA |
replace Puts a changed segment back into a database. You must first use a get...forUpdate, get next...forUpdate, or get next inParent...forUpdate statement (generating a DL/I GHU, GHN, or GHNP statement) to locate and hold the record. Under no circumstances can you update multiple database segments with a single default EGL replace statement. |
CALL 'CBLTDLI' USING EZEDLI-REPL EZEPCB-MASK01 EZEORSEG-IO-AREA |
The EGL set keyword (specifically the set record position statement) also supports DL/I. This keyword performs no I/O, but effectively locates a specified segment within a database. For details on how the keyword operates, see set.
You create a record that is based on the PSBRecord part, then assign the record name to the program psb property. EGL uses the record to generate the code that creates and validates DL/I calls.
Within each PCB record, you use the complex property @PCB to define the type and name of the PCB, and in some cases the hierarchy of the segments visible to that PCB. For details on the record types, see PCB record part propertiesand Record types and properties.
Finally, you may create a fixed record that is based on the predefined record part PSBDataRecord. You can use the record to interact with the system variable DLILib.psbData, which contains both the name of the runtime PSB and an address with which that PSB is accessed. The record is useful if you need to pass the PSB (really, a name and address) to another program or to receive the PSB from another program.
Each segment type that you want to access in a DL/I database must have an equivalent record of type DLISegment in your program.
Consider the sample customer database and related code in Example DL/I database. For each customer there are segments for credit status, history, and individual locations. Each location has order segments, and each order has line item segments. In this case you will create DLISegment type records for Customer, Credit, History, Location, Order, and Line Item.
In the absence of a #dli directive, EGL builds default segment search arguments (SSAs) to locate specific DL/I segments. As shown in the next example, the hostVarQualifier property of a DLISegment record part identifies a record that will contain a key value used in a default SSA .
Record myCustomerRecordPart type DLISegment { segmentName="STSCCST", keyItem="customerNo" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field ... end Record myLocationRecordPart type DLISegment { segmentName="STSCLOC", keyItem="locationNo" } 10 locationNo char(6) { dliFieldName = "STQCLNO" }; //key field ... end Record myCustomerPSBRecordPart type PSBRecord { defaultPSBName="STBICLG" } // database PCB customerPCB DB_PCBRecord { @PCB { pcbType = DB, pcbName = "STDCDBL", hierarchy = [ @Relationship { segmentRecord = "myCustomerRecordPart" }, @Relationship { segmentRecord = "myLocationRecordPart", parentRecord="myCustomerRecordPart" }, ...]}}; end
Program myProgram { @DLI{ psb = "myCustomerPSB" }} //define variables myCustomerPSB myCustomerPSBRecordPart; myCustomer myCustomerRecordPart; myLocation myLocationRecordPart;
get myLocation;
GU STSCCST (STQCCNO = :myCustomerRecordPart.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)
Notice that while EGL correctly associated the variable myLocation with the segment STSCLOC, EGL was unable to find the myCustomer variable. EGL knew only that myLocation is of type myLocationRecordPart, whose parent segment is myCustomerRecordPart, and that the keyItem for myCustomerRecordPart is customerNo.
Record myCustomerRecordPart type DLISegment { segmentName="STSCCST", hostVarQualifier="myCustomer", keyItem="customerNo" }
GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)
You also could use the property hostVarQualifier to refer to a field in a record that is not based on a segment in the database. For example, if you want EGL to look for the key value of the customer segment in a basic record (such as a transaction record), you must assign the name of that record to the hostVarQualifier property.
If you are working with a DLISegment record field whose name does not match the name of the equivalent database-segment field, set the record-field property dliFieldName to the name of the segment field.
In CICS, you can schedule the PSB identified in psbName; and the scheduling occurs after psbRef is cleared by a commit. To use this capability, set psbRef to a 0.
Record myCustomerRecordPart type DLISegment { segmentName="STSCCST", keyItem="customerNo" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field 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
For the complete record layouts in this example database, see Example DL/I database.
Such record declarations describe the structure of the database segments as visible to this program. At run time, the runtime PCB determines what an individual program can see.
The structure within a record must match the structure of the segment as DL/I presents it to the program. Define the keyItem and lengthItem fields with the same length and position that they have in the DL/I segment. If the segment is a logical child, the structure should include the concatenated key of the destination parent as well as the intersection data. If the segment is a concatenated segment in a logical database, the structure should include the concatenated key, the intersection data, and the destination parent segment.
Because DL/I databases are hierarchical, your program must keep track of the current location within the database. To locate a specific child segment, you must specify the parent segment for that child (if any), the parent segment for that parent (if any), and so on all the way to the root of the database.
//create instances of the records myCustomer myCustomerRecordPart; myLocation myLocationRecordPart; myOrder myOrderRecordPart; myItem myItemRecordPart; //build a segment search argument myCustomer.customerNo = "5001"; myLocation.locationNo = "22"; myOrder.orderDateNo = "20050730A003"; myItem.itemInventoryNo = "CHAIR"; //1st part compound key myItem.itemLineNo = 27; //get the item and hold it try get myItem forUpdate; onException myErrorHandler(2); end
At run time, DL/I will perform a GU (get unique) call with a 30-byte concatenated segment search argument that includes the key fields for customer (6 bytes), location (6 bytes), order (12 bytes), and item (6 + 2 bytes).
Related concepts
Basic DL/I database concepts
Record types and properties
Set-value blocks
Related tasks
EGL system exceptions
Displaying implicit DL/I code
Related reference
#dli directive
@DLI
add
delete
EGL library DLILib
EGL library VGLib
Example DL/I database
get
get next
get next inParent
IMS and DL/I error codes
PCB record part properties
replace
set