Executing Other Maintain Data Procedures

Topics:

You can call one Maintain Data procedure from another with the CALL command. Maintain Data procedure here means any procedure of Maintain Data language commands. CALL simplifies the process of modularizing an application. Software designed as a group of related modules tends to be easier to debug, easier to maintain, and lends itself to being reused by other applications, all of which increase your productivity.

CALL also makes it easy to partition an application, deploying each type of logic on the platform on which it will run most effectively.

The following diagram illustrates how to describe the relationship between called and calling procedures. It describes a sequence of five procedures from the perspective of the middle procedure, which is named C.

Note: A root procedure is also called the starting procedure.


diagram illustrates how to relationships between called calling

Calling a Maintain Data Procedure on a Different Server

If parent and child Maintain Data procedures reside on different servers, you identify the location of the child procedure by supplying the AT server phrase in the CALL command.

Example: Calling the EmpUpdat Procedure on a Different Server

Consider the EmpUpdat procedure:

MAINTAIN FILE Employee
FOR ALL NEXT Emp_ID INTO EmpStack;
.
.
.
CALL NewClass;
.
.
.
END

This calls the NewClass procedure on the EducServ Reporting Server:

MAINTAIN
.
.
.
END

In this example, EmpUpdat is the parent procedure and NewClass is the child procedure. When the child procedure, and any procedures that it has invoked, have finished executing, control returns to the parent.

Passing Variables Between Procedures

All user variables (both stacks and simple, or scalar variables) are global to a function or procedure, but not global to the project. In other words, to protect them from unintended changes in other parts of a project, you cannot directly reference a variable outside of the procedure in which it is found (with the exception of the FocError transaction variable). However, you can access the variable data in other procedures, simply by passing it as an argument from one procedure to another.

To pass variables as arguments, you only need to name them in the CALL command, and then again in the corresponding MAINTAIN command, using the FROM phrase for input arguments and INTO phrase for output arguments. Some variable attributes must match in the CALL and MAINTAIN commands:

  • Number. The number of arguments in the parent and child procedures must be identical.
  • Sequence. The order in which you name stacks and simple variables must be identical in the CALL and corresponding MAINTAIN commands.
  • Data type. Stack columns and simple variables must have the same data type (for example, integer) in both the parent and child procedures.
  • Stack column names. The names of stack columns need to match. If a column has different names in the parent and child procedures, it is not passed.

Other attributes do not need to match:

  • Stack and scalar variable names. The names of stacks and simple variables specified in the two commands do not need to match.
  • Other data attributes. All other data attributes, such as length and precision, do not need to match.
  • Simple variables. If you pass an individual stack cell, you must receive it as a simple variable, not as a stack cell.

After you have passed a variable to a child procedure, you need to define it in that procedure. How you define it depends upon the type of variable:

  • User-defined columns and fields. You must redefine each user-defined variable using a DECLARE or COMPUTE command. You only need to specify the variable format, not its value. For example, the following DECLARE command redefines the Counter field and the FullName column:
    DECLARE Counter/A20;
            EmpStack.FullName/A15;
  • Data source and virtual stack columns. You can define the data source columns and virtual columns of the stack in one of two ways. You can define them implicitly, by referring to the stack columns in a data source command, or explicitly, by referring to them using the INFER command. For example:
    INFER Emp_ID Pay_Date INTO EmpStack;

    The INFER command declares data source fields and the stack with which they are associated. You can specify one field for each segment you want in the stack or simply one field each from the anchor and target segments of a path you want in the stack.

    While INFER reestablishes the definition of the stack, it does not retrieve any records from the data source.

After a variable has been defined in the child procedure, its data becomes available. If you refer to stack cells that were not assigned values in the parent procedure, they are assigned default values, such as spaces or zeros (0), in the child procedure, and a message is displayed warning that they have not been explicitly assigned any values.

When the child procedure returns control back to the parent procedure, the values of stacks and simple variables specified as output arguments are passed back to the parent. The values of stacks and simple variables specified only as input arguments are not passed back.

Example: Passing Data Between Maintain Data Procedures

This procedure

MAINTAIN FILE Employee
FOR ALL NEXT Emp_ID INTO EmpStack;
.
.
.
CALL NewClass FROM EmpStack CourseStack INTO CourseStack;
.
.
.
END

calls the NEWCLASS procedure:

MAINTAIN FROM StudentStack CourseStack INTO CourseStack
.
.
.
END

EmpStack and CourseStack in the parent procedure correspond to StudentStack and CourseStack in the child procedure.

Accessing Data Sources in the Child Procedure

If a child procedure accesses a data source, whether retrieving or writing records, you must specify the data source in the MAINTAIN command. This is done the same way as for a stand-alone procedure. For example, the procedure below specifies the Employee and EducFile data sources:

MAINTAIN FILES Employee AND EducFile FROM StuStk INTO CoursStk
.
.
.
END

Data Source Position in Child Procedures

Each Maintain Data procedure tracks its own position in the data source. When you first call a procedure, Maintain Data positions you at the beginning of each segment in each data source accessed within that procedure. After navigating through a data source, you can reposition to the beginning of a segment by issuing the REPOSITION command. The data source positions are independent of the positions established in other procedures.

When a child procedure returns control to its parent, by default it clears its data source positions. You can specify that it retain its positions for future calls by using the KEEP option, as described in Optimizing Performance: Data Continuity and Memory Management.

Advantages of Modularizing Source Code Using CALL

Modularizing source code into several procedures has many advantages. One benefit is that you can use multiple procedures, run using the CALL command, to share common source code among many developers, speeding up both development and maintenance time. For example, a generalized error message display procedure could be used by all App Studio Maintain Data developers. After passing a message to the generalized procedure, the procedure would handle message display. The developers do not need to worry about how to display the message, and the error messages will always look consistent to end users.

Another advantage of modular design is that you can remove infrequently-run source code from a procedure and move it into its own procedure. This reduces the size of the original procedure, simplifying its logic, making maintenance easier, and using less memory if the new procedure is not called.

Optimizing Performance: Data Continuity and Memory Management

By default, when you terminate a child procedure, Maintain Data clears its data from memory to save space. You can optimize your application performance by specifying, each time you terminate a child procedure, how you want Maintain Data to handle the procedure data. You have two options, based on how often you will call a given procedure over the course of an application. If you will call the procedure:

  • Frequently, use the KEEP option to make the procedure run faster by retaining its data between calls.

    This option provides data continuity. The procedure data carries over from the end of one invocation to the beginning of the next. The next time you call the procedure, its variables and data source position pointers start out with the same values that they held when the procedure was last terminated. You can use these values or reinitialize them using the DECLARE (or COMPUTE) and REPOSITION commands.

    Of course, variables passed by the parent procedure are not affected by data continuity since the child procedure receives them directly from the parent procedure at the beginning of each call.

    KEEP affects transaction integrity in the following way. The KEEP option does not issue an implied COMMIT command at the end of a child procedure. When a child procedure with an open logical transaction returns to its parent procedure and specifies KEEP, the transaction continues into the parent.

  • Rarely, use the RESET option to reduce memory consumption by freeing the procedure data at the end of each call.

    This option does not provide data continuity. All of the procedure variables and data source position pointers are automatically initialized at the beginning of each procedure.

    RESET affects transaction integrity in the following way. The RESET option issues an implied COMMIT command at the end of a child procedure. When a child procedure with an open logical transaction returns to its parent procedure using RESET, the transaction is closed at the end of the child procedure.

You can specify how a procedure will handle its data in memory by terminating it with the GOTO END command qualified with the appropriate memory-management phrase. The syntax is

GOTO END [KEEP|RESET];

where:

KEEP

Terminates the procedure, but keeps its data, the values of its variables and data source position pointers, in memory. It remains in memory through the next invocation, or (if it is not called again) until the application terminates. The procedure does not issue an implied COMMIT command to close an open logical transaction.

RESET

Terminates the procedure, clears its data from memory, and issues an implied COMMIT command to close an open logical transaction. RESET is the default value.

You can use both options in the same procedure. For example, when you are ready to end a child procedure, you could evaluate what logic the procedure will need to perform when it is next called and then branch accordingly either to keep data in memory, saving time and providing data continuity, or else to clear data from memory to conserve space.

WebFOCUS

Feedback