COBOL cookbook¶
Practical recipes for the plxcobol dialect (ISO/IEC 1989:2023). Every recipe here was run on PostgreSQL; plx transpiles the body to plpgsql and the standard interpreter executes it. See the plxcobol chapter for the full language reference.
Absolute value with IF / ELSE¶
A scalar function branches with IF ... ELSE ... END-IF and returns with GOBACK RETURNING. The result variable is declared with a signed picture.
CREATE FUNCTION abs_val(n int) RETURNS int LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-R PIC S9(9).
PROCEDURE DIVISION.
IF N < 0
COMPUTE WS-R = 0 - N
ELSE
MOVE N TO WS-R
END-IF
GOBACK RETURNING WS-R.
$$;
Factorial with an accumulating loop¶
PERFORM VARYING ... UNTIL ... END-PERFORM is the counted loop. Here it multiplies a running product across the range. The accumulator starts at 1 with a VALUE clause.
CREATE FUNCTION factorial(n int) RETURNS bigint LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-RESULT PIC 9(18) VALUE 1.
01 WS-I PIC 9(9).
PROCEDURE DIVISION.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > N
COMPUTE WS-RESULT = WS-RESULT * WS-I
END-PERFORM
GOBACK RETURNING WS-RESULT.
$$;
Classifying with EVALUATE¶
EVALUATE over a subject maps to a CASE. Stacked WHEN values share the statements that follow them, and WHEN OTHER is the default.
CREATE FUNCTION weekday_name(n int) RETURNS text LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-R PIC X(9).
PROCEDURE DIVISION.
EVALUATE N
WHEN 1
MOVE "Monday" TO WS-R
WHEN 6
WHEN 7
MOVE "weekend" TO WS-R
WHEN OTHER
MOVE "weekday" TO WS-R
END-EVALUATE
GOBACK RETURNING WS-R.
$$;
Building a string in a loop¶
STRING-APPEND <expr> TO <var> lowers to the plx string builder, whose append is amortized O(1) on PostgreSQL 18. Non-text operands are coerced, so a numeric counter can be appended directly.
CREATE FUNCTION number_list(n int) RETURNS text LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-OUT PIC X(1) VALUE "".
01 WS-I PIC 9(9).
PROCEDURE DIVISION.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > N
STRING-APPEND WS-I TO WS-OUT
STRING-APPEND "," TO WS-OUT
END-PERFORM
GOBACK RETURNING WS-OUT.
$$;
A table with OCCURS¶
OCCURS n TIMES makes an item a table, mapped to a PostgreSQL array. A subscript WS-ARR(i) is 1-based and is recognized in COMPUTE targets and expressions. This fills a table of squares, then reads one element back.
CREATE FUNCTION nth_square(n int) RETURNS int LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-ARR PIC 9(9) OCCURS 10 TIMES.
01 WS-I PIC 9(9).
01 WS-OUT PIC 9(9).
PROCEDURE DIVISION.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10
COMPUTE WS-ARR(WS-I) = WS-I * WS-I
END-PERFORM
COMPUTE WS-OUT = WS-ARR(N)
GOBACK RETURNING WS-OUT.
$$;
Looping over a query result¶
PERFORM <record> OVER "<sql>" runs the loop body once per row. Field access is <record>.<column>, and USING supplies bind parameters. This example assumes a table:
CREATE TABLE orders (id int, grp int, amount int);
INSERT INTO orders VALUES (1,1,100),(2,1,250),(3,1,75),(4,2,500);
CREATE FUNCTION order_total(g int) RETURNS bigint LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-TOTAL PIC 9(18) VALUE 0.
01 WS-R TYPE RECORD.
PROCEDURE DIVISION.
PERFORM WS-R OVER "SELECT amount FROM orders WHERE grp = $1" USING G
ADD WS-R.AMOUNT TO WS-TOTAL
END-PERFORM
GOBACK RETURNING WS-TOTAL.
$$;
A set-returning function¶
A function that returns SETOF emits rows with RETURN-NEXT. Each RETURN-NEXT adds one value to the result set; the function ends with a plain GOBACK.
CREATE FUNCTION squares(n int) RETURNS SETOF int LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-I PIC 9(9).
PROCEDURE DIVISION.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > N
RETURN-NEXT WS-I * WS-I
END-PERFORM
GOBACK.
$$;
Dynamic SQL with EXECUTE¶
EXECUTE "<sql>" runs a command built at run time, with USING binds and an INTO target for a scalar result. This counts the rows meeting a threshold on the orders table from the query recipe above.
CREATE FUNCTION count_big(threshold int) RETURNS bigint LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-COUNT PIC 9(18).
PROCEDURE DIVISION.
EXECUTE "SELECT count(*) FROM orders WHERE amount >= $1" USING THRESHOLD INTO WS-COUNT
GOBACK RETURNING WS-COUNT.
$$;
PICTURE clauses and their SQL types¶
A PICTURE clause chooses the SQL type of a local. PIC 9(9) is integer, a signed implied-decimal PIC S9(5)V9(4) is numeric(9,4), and PIC X(20) is varchar(20). This function uses one of each and returns a formatted line.
CREATE FUNCTION picture_demo(n int, rate numeric, name text) RETURNS text LANGUAGE plxcobol AS $$
WORKING-STORAGE SECTION.
01 WS-COUNT PIC 9(9).
01 WS-RATE PIC S9(5)V9(4).
01 WS-NAME PIC X(20).
01 WS-OUT PIC X(40) VALUE "".
PROCEDURE DIVISION.
MOVE N TO WS-COUNT
MOVE RATE TO WS-RATE
MOVE NAME TO WS-NAME
COMPUTE WS-RATE = WS-RATE * WS-COUNT
STRING-APPEND WS-NAME TO WS-OUT
STRING-APPEND " total=" TO WS-OUT
STRING-APPEND WS-RATE TO WS-OUT
GOBACK RETURNING WS-OUT.
$$;
The signed four-place scale keeps WS-RATE as numeric(9,4), so 1.5 * 3 prints as 4.5000.
COMPUTE with an arithmetic expression¶
COMPUTE evaluates a full expression, with ** for exponent and a CONSTANT AS value for a named constant. This computes the area of a circle.