RPGLE Fully Free Program Generator with Embedded SQL and MONITOR
This generator writes a complete fully free ILE RPG program for IBM i 7.3, 7.4 and 7.5 that reads a table with an embedded SQL cursor, checks SQLCODE after every statement and traps runtime errors with MONITOR. Fill in your table and columns, copy the source to a stream file, and compile it with the CRTSQLRPGI command shown.
Fill in
Must match the column: check with DSPFFD or QSYS2.SYSCOLUMNS.
CUSTRPT.sqlrpgle
**FREE
ctl-opt dftactgrp(*no) actgrp(*new) option(*srcstmt : *nodebugio);
// One row from MYLIB.CUSTMAST; types must match the columns
dcl-ds row qualified;
CUSNO packed(7:0);
CUSNAM char(30);
CUSBAL packed(11:2);
end-ds;
dcl-s rows int(10) inz(0);
dcl-s total packed(15:2) inz(0);
dcl-s avgAmt packed(15:2) inz(0);
dcl-s msg varchar(52);
// SET OPTION must come before any other SQL statement in the source
exec sql set option commit = *NONE, naming = *sql,
closqlcsr = *endmod, datfmt = *iso;
exec sql declare c1 cursor for
select CUSNO, CUSNAM, CUSBAL
from MYLIB.CUSTMAST
where CUSBAL > 0
order by CUSNO
for read only;
exec sql open c1;
if sqlcode < 0;
dsply ('Open failed SQLCODE ' + %char(sqlcode));
*inlr = *on;
return;
endif;
dow 1 = 1;
exec sql fetch next from c1 into :row;
if sqlcode = 100; // no more rows (SQLSTATE 02000)
leave;
elseif sqlcode < 0;
dsply ('Fetch failed SQLCODE ' + %char(sqlcode));
leave;
endif;
monitor;
rows += 1;
total += row.CUSBAL;
avgAmt = total / rows;
msg = %char(row.CUSNO) + ' ' + %trim(row.CUSNAM)
+ ' ' + %char(row.CUSBAL);
dsply msg;
on-error 00102 : 00103; // divide by zero, result too large
dsply ('Calculation error on ' + %char(row.CUSNO));
on-error *program;
dsply ('Unexpected error ' + %char(%status));
leave;
endmon;
enddo;
exec sql close c1;
dsply ('Rows ' + %char(rows) + ' total ' + %char(total) + ' avg ' + %char(avgAmt));
*inlr = *on;
return;Compile and run (CL)
CRTSQLRPGI OBJ(MYLIB/CUSTRPT) SRCSTMF('/home/dev/CUSTRPT.sqlrpgle') OBJTYPE(*PGM) COMMIT(*NONE) DBGVIEW(*SOURCE)
CALL PGM(MYLIB/CUSTRPT)Optional: write rows to a table instead of DSPLY
// Replace the dsply msg; line inside the loop with:
exec sql insert into MYLIB.CUSTRPTOUT
(CUSNO, CUSNAM, CUSBAL)
values (:row.CUSNO, :row.CUSNAM, :row.CUSBAL);
if sqlcode < 0;
dsply ('Insert failed SQLCODE ' + %char(sqlcode));
endif;
// Create the output table once, for example in Run SQL Scripts:
// CREATE TABLE MYLIB.CUSTRPTOUT AS
// (SELECT CUSNO, CUSNAM, CUSBAL FROM MYLIB.CUSTMAST)
// WITH NO DATA;Fully free source (**FREE in column 1) needs IBM i 7.1 TR11 or 7.2 TR3 or later with the compiler PTFs; it is standard on 7.3, 7.4 and 7.5. Check each RPG type against the column definition (DSPFFD or QSYS2.SYSCOLUMNS); a mismatch gives SQLCODE errors on FETCH or decimal data errors. DSPLY shows at most 52 characters. With COMMIT(*CHG) the table must be journaled and inserts need a COMMIT. The output table name in the optional block must be 10 characters or fewer for system naming.
Get your RPG program reviewed
Send a generated or existing SQLRPGLE program and we will check types, SQL error handling and compile options for your release.
Optional. The tool and every export work without this. No spam.
How to use it
Enter the library, table and three columns: a key, a name and an amount. For each column give the RPG type that matches its definition, for example packed(7:0) for a DECIMAL(7,0) column or char(30) for CHAR(30); DSPFFD or QSYS2.SYSCOLUMNS shows the definitions. Choose *NONE for commitment control unless the table is journaled and you plan to write. Save the first block as a stream file, for example /home/dev/CUSTRPT.sqlrpgle, from VS Code with Code for IBM i, RDi, or EDTF, then run the CRTSQLRPGI command and CALL the program. Each row appears as a DSPLY message, followed by a count, total and average.
- Source member alternative: SRCFILE(MYLIB/QRPGLESRC) SRCMBR(CUSTRPT) with type SQLRPGLE
- Run from an interactive session to see DSPLY output
- Use the optional block to write rows to a table for batch use
What each part does
ctl-opt dftactgrp(*no) is required to use procedures and named activation groups; actgrp(*new) gives each call a clean activation group. option(*srcstmt) makes job log statement numbers match your source lines. The qualified data structure row is the host structure for FETCH, so one FETCH fills all three subfields. SET OPTION fixes commitment control, SQL naming (library.table), cursor closing and date format at compile time, and it must be the first SQL statement in the source. SQLCODE 100 means no more rows, negative values are errors; SQLSTATE '02000' is the equivalent end-of-data test if you prefer SQLSTATE. MONITOR traps runtime errors in the loop body, with specific status codes listed before the catch-all on-error *program.
Worked example
With the defaults the program reads MYLIB.CUSTMAST where CUSBAL > 0 in CUSNO order. For a customer 1001 named ACME TOOLING with a balance of 2,450.00 the DSPLY line reads '1001 ACME TOOLING 2450.00'. After the last row the program shows 'Rows 214 total 386112.50 avg 1804.26' (your numbers will differ). If the cursor finds no rows the loop exits on the first FETCH with SQLCODE 100 and the summary shows zero rows. If an amount column was defined as zoned in the file but packed here, you get a FETCH error or decimal data error, which is why the types are separate fields.
Version notes and gotchas
**FREE must start in column 1 of line 1; nothing else can be on that line. Fully free source arrived with 7.1 TR11 and 7.2 TR3 and is standard from 7.3. SRCSTMF on CRTSQLRPGI lets you keep source in the IFS and in Git; a source member works the same. DSPLY truncates at 52 characters and is not meant for batch jobs, where it waits for a reply; use the table output block or a printer file for batch. With naming = *sql, unqualified table names resolve to a schema named after the user, so always qualify, or switch to naming = *sys and the library list.
Frequently Asked Questions
What does a simple RPG program look like?
A modern RPG program starts with **FREE, a ctl-opt line, declarations with dcl-s and dcl-ds, then calculations in free format ending with *inlr = *on and return. The generated program is a realistic example: it declares a data structure, opens an SQL cursor, loops through the rows, handles errors and prints a summary.
Is RPG IV still used on IBM i?
Yes. ILE RPG (RPG IV) is the main business language on IBM i and still gets enhancements through Technology Refreshes, including fully free syntax, embedded SQL improvements and new built-in functions. Many ERPs that run on IBM i, such as Infor LX and XA, JD Edwards World and in-house systems, are written in RPG.
How do I handle errors in an SQLRPGLE program?
Check SQLCODE or SQLSTATE after every EXEC SQL statement: 0 is success, 100 (SQLSTATE 02000) is no data, negative is an error, positive other than 100 is a warning. For RPG runtime errors, wrap code in MONITOR with ON-ERROR status codes. SQL errors do not trigger MONITOR, so both checks are needed.
How should a beginner start with RPG programming?
Start with fully free RPG and embedded SQL rather than fixed-format cycle code: it reads like other languages and is what new code uses. Use VS Code with Code for IBM i or RDi, compile programs like this one, step through them with the debugger, and read the ILE RPG Reference for each opcode you use.
If your RPG team wants an assistant that explains existing programs, drafts SQL and answers questions about your IBM i data in plain English, we can run it privately on your own servers.
Related Tools
IBM i RPGLE Service Program Generator (NOMAIN, Binder Source, CRTSRVPGM)
Generate a complete ILE RPG service program kit: NOMAIN module with exported procedures, prototype copybook, binder source with a signature, binding directory and the CL to build and call it.
Developer ToolsIBM i ILE RPG Status Codes and Common Error Messages Reference
Look up ILE RPG program and file status codes with IBM's wording, the MONITOR or %ERROR pattern that traps each one, and the usual fix, plus the CPF and MCH messages behind them.
Developer ToolsIBM i (DB2 for i) SQL Data Extraction Script Generator
Generate DB2 for i SQL to inspect a file, count rows, and extract records with Julian date filters for JD Edwards World or other IBM i data.
Developer ToolsIBM i Services (QSYS2 and SYSTOOLS) SQL Reference
Searchable list of IBM i Services you can query with SQL from Run SQL Scripts, STRSQL or ODBC, with the CL command each replaces and a ready-to-run statement.
More Developer Tools tools
See all- IBM i Query/400 (WRKQRY) Record Selection Tests and Result Field Reference
- IBM i Journal Receiver Growth and Retention Calculator
- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton
Keep exploring
Free tools
- IBM i RPGLE Service Program Generator (NOMAIN, Binder Source, CRTSRVPGM)Generate a complete ILE RPG service program kit: NOMAIN module with exported procedures, prototype copybook, binder source with a signature, binding directory and the CL to build and call it.
- IBM i ILE RPG Status Codes and Common Error Messages ReferenceLook up ILE RPG program and file status codes with IBM's wording, the MONITOR or %ERROR pattern that traps each one, and the usual fix, plus the CPF and MCH messages behind them.
- IBM i (AS/400) Custom RPG Applications Private AI Layer Blueprint GeneratorFill in your IBM i RPG environment and export an architecture plan for a private, on-prem AI assistant: components, security controls, rollout and open questions.
ERP fixes and how-tos
- How to Add AI to an IBM i (AS/400) RPG Application Without Moving ItHow to add a private AI assistant to custom RPG applications on IBM i: Db2 for i access, field names, journals, RCAC security, local LLM, sizing and rollout.
- Infor XA REST API: expose XA through IBM i Integrated Web Services or IONHow to expose Infor XA (MAPICS) data and functions as REST on IBM i using Integrated Web Services or ION, with an example call and the safety rules for writes.
- How to Monitor ERP Performance: What to Track and Alert OnWhat an IT manager should monitor to keep an ERP fast: user response time, database waits and blocking, batch job duration, queues and storage.
Integrations
- How to add AI agents to JD Edwards World on IBM iHow to add AI agents to JD Edwards World on IBM i: a read-first tool layer over DB2 for i, human approval before any write, and a fully on-prem model option.
- How to add AI agents to Infor XA on IBM iHow to add AI agents to Infor XA on IBM i: a tool layer over Db2 for i and RPG programs, approval gates, on-prem models, and realistic expedite and exception flows.