The default get next statement starts at the current position in the database and searches through the entire database for the next occurrence of the target segment under any parent. To limit the scope of the search to the currently established dependent chain, use the get next inParent statement.
get myOrder with #dli {
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STSOCORD (STQCODN = :myOrder.orderDateno) };
get next inParent myItem;
while (myItem not noRecordFound)
// process the current item
get next inParent myItem;
end
GNP STLCITM
targetBalance decimal(12,2);
targetBalance = 10,000.00;
get next myCustomer,myCrStatus with #dli{
GU STSCCST*D STSCSTA (STFCSBL >= :targetBalance) };
Record CustomerData type basicRecord
10 customerNo char(6)
...
end
Program myProgram
(customerParm CustomerData)
{ @DLI{ psb = "myCustomerPSB" }}
//declare variables
myCustomerPSB CustomerPSBRecordPart;
myCustomer CustomerRecordPart;
myCustomer.customerNo = CustomerParm.customerNo;
get myCustomer;
GU STSCCST (STQCCNO = :myCustomer.customerNo)
The
advantage of this technique is that it is very simple. The disadvantage
is the very slight performance overhead of moving the customer number
to the segment record.get myCustomer with #dli {
GU STSCCST (STQCCNO = :customerParm.customerNo) } ;
This
technique avoids the performance overhead of moving the customer number.
However, it does take slightly longer to paste in the default #dli
directive and then modify the code to use the correct record variable
name for the parameter record.Record CustomerRecordPart type DLISegment
{segmentName="STSCCST", keyItem="customerNo",
hostVarQualifier="customerParm" }
10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field
...
end
get myCustomer;
GU STSCCST (STQCCNO = :customerParm.customerNo)
The advantage of this technique is that it results in the same pseudo-DL/I code that you coded for the #dli directive, without you actually having to code the #dli directive. The disadvantage is that EGL now uses customerParm as the qualifier for every implicit DL/I database I/O statement that uses the CustomerRecordPart.
You can use implicit DL/I database I/O to retrieve a non-root segment. EGL creates the entire chain of SSAs for you based on the hierarchical position of the target segment in the PCB. However, for the higher level segments in the hierarchy, EGL cannot automatically determine the name of the program variable to use as the qualifier for the segment.
myCustomer CustomerRecordPart;
myLocation LocationRecordPart;
get myLocation;
EGL
will create the following pseudo-DL/I code: GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
Notice that while EGL correctly associated the variable myLocation with the segment STSCLOC, EGL was unable to find the variable myCustomer that is based on the CustomerRecordPart. EGL only knows that myLocation is of type LocationRecordPart, whose parent segment is CustomerRecordPart, and that the keyItem for CustomerRecordPart is customerNo.
CustomerRecordPart CustomerRecordPart;
EGL
creates the same pseudo-DL/I code: GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
Because EGL creates the default SSAs from the PCB hierarchy information, this is an easy way of ensuring that the variable names EGL uses match your program's record variable declarations. The disadvantage is that this technique does not follow the general practice of using different names for parts and variables.
get myLocation with #dli {
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
The advantage of this technique is that it is very clear which host variables are being used. It is an easy technique to use if the host variable qualifier or field name is different from the record variable that is based on the DL/I segment record. The disadvantage is the same as for any explicit I/O -- if the hierarchy or the key fields change, the explicit DL/I database I/O statement does not change automatically.
Record CustomerRecordPart type DLISegment
{ segmentName="STSCCST", keyItem="customerNo",
hostVarQualifier = "myCustomer" }
10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field
...
end
Now if you use the following get statement:get myLocation;
EGL
will produce the correct pseudo-DL/I code:GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
The advantage of this technique is that you can use implicit DL/I database I/O and have different names for the record variables and the DL/I segment records. The disadvantage is that EGL now uses myCustomer as the qualifier for every implicit DL/I database I/O statement that uses the CustomerRecordPart.
// database PCB for customer by Name
customerNamePCB DB_PCBRecord
{ @PCB { pcbType = DB, pcbName = "STDCNAM",
secondaryIndex = "STUCCNM",
hierarchy = [ @relationship { segmentRecord = "CustomerRecordPart" },
... ] }
}
The pcbName property must match an actual DL/I database PCB in the runtime PSB. The secondaryIndex property must provide the same field name as your database administrator specifies in the XDFLD statement of the runtime PCB. There are now two PCB records in the PSB record that include the CustomerRecordPart in their hierarchy.
myCustomer CustomerRecordPart;
get myCustomer;
EGL will create the pseudo-DL/I code based
on the first PCB record in the PSB record that includes the CustomerRecord
part.get myCustomer usingPCB customerNamePCB;
EGL
will create the following pseudo-DL/I code:GU STSCCST (STUCCNM = :myCustomer.customerName)
// orders view of customer database
ordersByReferencePCB DB_PCBRecord
{ @PCB { pcbType = DB, pcbName = "STDCDBL",
secondaryIndex = "STFCORF", //use DL/I name
hierarchy = [
@relationship { segmentRecord = "OrderRecordPart" },
@relationship { segmentRecord = "LocationRecordPart",
parentRecord = "OrderRecordPart" },
@relationship { segmentRecord = "CustomerRecordPart",
parentRecord = "LocationRecordPart" },
@relationship { segmentRecord = "ItemRecordPart",
parentRecord = "OrderRecordPart" }
]}
};
end
get myOrder, myCustomer with #dli{
GU STPCORD*D (STQCODN = :myOrder.orderReference)
STSCLOC
STSCCST };
get myCustomer, myLocation, myOrder;
This
statement generates the following DL/I pseudocode:GU STSCCST*D (STQCCNO = :myCustomer.customerNo)
STSCLOC*D (STQCLNO = :myLocation.locationNo)
STPCORD (STQCDDN = :myOrder.orderDateNo)
get myCustomer, myLocation, myOrder forUpdate;
replace myOrder with #dli{
REPL STSCCST*N
STSCLOC*N
STPCORD };
The default DL/I call EGL builds for
a delete function that follows a get
forUpdate statement with D command codes does not delete
each segment retrieved. It deletes only the target segment specified
on the delete statement.myHistory HistoryRecordPart
redefCustomer CustomerRecordPart {redefines=myHistory};
redefLocation LocationRecordPart {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
printCustomer();
when "STSCLOC" // it was a location
printLocation();
...
end
end
You can use the get and get next statements to retrieve DL/I segments to a dynamic array. Because there is no key field for the array itself (only for members of the array), you must use some special techniques so that EGL will create the correct code.
myCustomer CustomerRecordPart;
myLocation LocationRecordPart;
myOrder OrderRecordPart;
myOrderArray OrderRecordPart [] {maxsize = 20}; // array of orders
myCustomer.customerNo = "123456";
myLocation.locationNo = "ABCDEF";
myOrderDateNo = "20050730A003";
get myOrderArray; // fill the array the first time
... do some processing
get next myOrderArray; // get the next batch of 20 orders
get myOrderArray with #dli{
GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo)
STSCLOC (STQCLNO = :LocationRecordPart.locationNo)
STPCORD (STQCODN = :OrderRecordPart.orderDateNo)
GN STPCORD };
get next myOrderArray with #dli{
GN STPCORD };
Filling the dynamic array for the first batch of 20 orders with a get statement requires an initial GU call followed by a loop of GN calls until the array is full or DL/I runs out of segment occurrences. In the pseudo-DL/I code that EGL creates, the GU call retrieves the first order segment. EGL treats the GN call as a loop and provides the logic to loop until the array is full or DL/I runs out of segment occurrences. Similarly, EGL treats the get next statement as a loop and provides the loop control logic for you.
Record CustomerRecordPart type DLISegment
{ segmentName="STSCCST", keyItem="customerNo" }
10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field
...
end
to the following:Record STSCCST type DLISegment
{ segmentName="STSCCST", keyItem="customerNo" }
10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field
...
end
Record CustomerPSBRecordPart type PSBRecord { defaultPSBName="STBICLG" }
// database PCB
customerPCB DB_PCBRecord { @PCB { pcbType = DB, pcbName = "STDCDBL",
hierarchy = [ @relationship { segmentRecord = "STSCCST" },
@relationship {segmentRecord="STSCLOC",
parentRecord="STSCCST"},
@relationship {segmentRecord="STPCORD",
parentRecord="STSCLOC"}
]}};
end
STSCCST STSCCST;
STSCLOC STSCLOC;
STPCORD STPCORD;
myOrderArray STPCORD [] {maxsize = 20}; // array of orders
get myOrderArray; // fill the array the first time
EGL
creates the following pseudo-DL/I code for the get statement
and the host variable qualifiers use the correct record variable names:get myOrderArray with #dli{
GU STSCCST (STQCCNO = :STSCCST.customerNo)
STSCLOC (STQCLNO = :STSCLOC.locationNo)
STPCORD (STQCODN = :STPCORD.orderDateNo)
GN STPCORD };
Because EGL creates the default SSAs from the PCB hierarchy information, this is an easy way of ensuring that the variable names EGL uses match your program's record variable declarations. The disadvantage is that this technique does not follow the general practice of using different names for parts and variables.
get myOrderArray with #dli{
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STPCORD (STQCODN = :myOrder.orderDateNo)
GN STPCORD };
myOrder.orderDateNo = "";
get myOrderArray with #dli{
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STPCORD (STQCODN >= :myOrder.orderDateNo) // using >= instead of =
GN STPCORD };
The disadvantage of this technique is the same as for any explicit I/O -- if the hierarchy or the key fields change, the explicit DL/I database I/O statement does not change automatically.
Record CustomerRecordPart type DLISegment
{ segmentName="STSCCST", keyItem="customerNo",
hostVarQualifier = "myCustomer" }
10 customerNo char(6) { dliFieldName = "STQCCNO" }; //key field
...
end
myCustomer CustomerRecodPart;
myLocation LocationRecordPart;
myOrder OrderRecordPart;
myOrderArray OrderRecordPart [] {maxsize = 20}; // array of orders
get myOrderArray; // fill the array the first time
get myOrderArray with #dli{
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STPCORD (STQCODN = :myOrder.orderDateNo)
GN STPCORD };
The advantage of this technique is that you can use implicit DL/I database I/O and have different names for the record variables and the DL/I segment records. The disadvantage is that EGL now uses myCustomer as the qualifier for every implicit DL/I database I/O statement that uses the CustomerRecordPart, LocationRecordPart, and OrderRecordPart.