Language Reference¶
A lookup reference for the 4GL language: every statement and built-in you are likely to use, with its syntax and a short example. For guided, worked introductions, follow the links back to the tutorial chapters; this page is the dictionary, not the lesson.
- Program structure
- Comments
- Data types
- Declarations
- Operators
- Control flow
- Screen input and output
- Windows and forms
- Menus
- Database and SQL
- Functions
- Built-in functions
- Reports
- System statements
- Stored procedures (SPL)
- Status and error variables
Program structure¶
| Statement | Purpose |
|---|---|
MAIN … END MAIN |
The program entry point (exactly one per program) |
FUNCTION … END FUNCTION |
A reusable block that may return values |
GLOBALS "file.4gl" |
Include shared global variables from a file |
GLOBALS … END GLOBALS |
Declare global variables (in a g_*.4gl file) |
GLOBALS "g_app.4gl"
MAIN
CALL greet("world")
END MAIN
FUNCTION greet(who)
DEFINE who CHAR(40)
DISPLAY "Hello, ", who CLIPPED
END FUNCTION
Comments¶
-- single line
# single line
{ block comment over
several lines }
Data types¶
| Type | Description |
|---|---|
CHAR(n) |
Fixed-length text (space-padded), up to 32,767 |
VARCHAR(n) |
Variable-length text, up to 32,767 |
STRING |
Variable-length text, up to 32,767 |
TEXT |
Long/unlimited text (blob) |
INTEGER |
32-bit whole number |
SMALLINT |
16-bit whole number |
DECIMAL(p,s) |
Exact decimal (p digits, s decimals) |
MONEY(p,s) |
Currency amount |
FLOAT |
Approximate floating point (avoid for money) |
DATE |
Calendar date |
DATETIME |
Date and time |
INTERVAL |
A span of time |
See Language Basics for guidance on choosing types.
Declarations¶
| Statement | Purpose |
|---|---|
DEFINE name type |
Declare a variable |
DEFINE a, b, c type |
Declare several of the same type |
DEFINE r RECORD … END RECORD |
Declare a record (group of fields) |
DEFINE r RECORD LIKE table.* |
A record matching a table's columns |
DEFINE a ARRAY[n] OF type |
Fixed-size array |
DEFINE a DYNAMIC ARRAY OF type |
Resizable array |
CONSTANT NAME = value |
A named constant |
Rule: all
DEFINEstatements must appear at the top of a function orMAIN, before any executable line.
Dynamic-array methods: .getLength(), .appendElement(), .deleteElement(i),
.clear().
Operators¶
| Category | Operators |
|---|---|
| Arithmetic | + - * / MOD ** (power) |
| Comparison | = != <> < <= > >= |
| Logical | AND OR NOT |
| NULL test | IS NULL IS NOT NULL |
| Text match | MATCHES "J*" LIKE "John%" |
| Concatenation | a CLIPPED, " ", b or a||b |
| Assignment | LET x = expr |
Control flow¶
IF cond THEN ... ELSE ... END IF
CASE value -- match a value
WHEN x ...
OTHERWISE ...
END CASE
CASE -- test conditions
WHEN cond1 ...
OTHERWISE ...
END CASE
WHILE cond ... END WHILE
FOR i = 1 TO n [STEP s] ... END FOR
FOREACH cursor INTO vars ... END FOREACH
| Statement | Purpose |
|---|---|
EXIT FOR / EXIT WHILE / EXIT FOREACH |
Leave the loop |
CONTINUE FOR / CONTINUE WHILE |
Skip to the next iteration |
EXIT PROGRAM [n] |
End the program (optional exit code) |
Prefer
CASEfor multi-way branches; avoidELSE IF(two words). See Language Basics.
Screen input and output¶
| Statement | Purpose |
|---|---|
DISPLAY expr [, expr …] |
Output text/values |
DISPLAY BY NAME var [, var …] |
Show variables in same-named fields |
DISPLAY expr TO field |
Show a value in a named field |
INPUT BY NAME var [, var …] |
Edit same-named fields |
INPUT var [, var] FROM field [, field] |
Edit named fields |
INPUT ARRAY a FROM screen.* |
Edit a list/grid |
DISPLAY ARRAY a TO screen.* |
Show a scrollable list |
CONSTRUCT where ON cols FROM flds |
Build a SQL WHERE clause from a search form |
PROMPT "text" FOR var |
Prompt for a single value |
MESSAGE "text" |
Show an informational line |
ERROR "text" |
Show an error line |
Control blocks inside INPUT, INPUT ARRAY and DISPLAY ARRAY:
| Block | Fires when… |
|---|---|
BEFORE INPUT |
Editing begins |
BEFORE FIELD f |
The cursor enters field f |
AFTER FIELD f |
The cursor leaves field f (validate here) |
ON ACTION name |
The user triggers an action |
BEFORE ROW / AFTER ROW |
The cursor moves between rows (arrays) |
BEFORE INSERT / AFTER INSERT |
A row is added (INPUT ARRAY) |
BEFORE DELETE / AFTER DELETE |
A row is removed (INPUT ARRAY) |
AFTER INPUT / AFTER DISPLAY |
Editing/display ends |
Inside these blocks: NEXT FIELD f (move the cursor), EXIT DISPLAY / ACCEPT INPUT,
and the helpers ARR_CURR() (current row) and SET_COUNT(n) (row count before
DISPLAY ARRAY). See Screens, Input and Menus and
Working with Arrays.
Windows and forms¶
| Statement | Purpose |
|---|---|
OPEN WINDOW w WITH FORM "name" |
Open a window showing a compiled form |
CLOSE WINDOW w |
Close a window |
CLOSE WINDOW screen |
Close the default text window |
CURRENT WINDOW IS w |
Make w the current window |
For the VDC client you do not position windows or place buttons by hand — see
Forms and Widgets. To control fields at run time, use the
ui.* calls in the UI Function Reference.
Menus¶
MENU "title"
COMMAND "Label"
-- code to run
ON ACTION name
-- code to run
COMMAND "Close"
EXIT MENU
END MENU
| Statement | Purpose |
|---|---|
COMMAND "Label" |
A menu action with the code that follows |
ON ACTION name |
Handle an action/key |
EXIT MENU |
Leave the menu loop |
HIDE OPTION "Label" / SHOW OPTION "Label" |
Hide/show an option |
Database and SQL¶
| Statement | Purpose |
|---|---|
DATABASE name |
Connect to a database |
CLOSE DATABASE |
Disconnect |
SELECT cols INTO vars FROM … |
Read a single row into variables |
DECLARE c CURSOR FOR SELECT … |
Declare a cursor for a multi-row query |
OPEN c [USING v] |
Open a cursor |
FETCH c INTO vars |
Fetch the next row |
CLOSE c |
Close a cursor |
FOREACH c INTO vars … END FOREACH |
Open, fetch every row, close — in one loop |
INSERT INTO t (cols) VALUES (…) |
Add a row |
UPDATE t SET col = v WHERE … |
Change rows |
DELETE FROM t WHERE … |
Remove rows |
PREPARE p FROM "sql with ?" |
Prepare a statement (with ? placeholders) |
EXECUTE p [USING v] [INTO out] |
Run a prepared statement |
FREE p |
Release a prepared statement / cursor |
BEGIN WORK |
Start a transaction |
COMMIT WORK |
Commit the transaction |
ROLLBACK WORK |
Undo the transaction |
WHENEVER ERROR STOP\|CONTINUE\|CALL f |
Default reaction to SQL errors |
WHENEVER NOT FOUND CONTINUE |
Default reaction to "no rows" |
Full worked examples are in Talking to the Database.
Functions¶
FUNCTION name(a, b)
DEFINE a INTEGER
DEFINE b INTEGER
RETURN a + b -- may return several values: RETURN x, y, z
END FUNCTION
CALL name(2, 3) RETURNING result
CALL do_something() -- a function that returns nothing
| Statement | Purpose |
|---|---|
CALL f(args) |
Call a function |
CALL f(args) RETURNING v |
Call and capture return value(s) |
RETURN [values] |
Return from a function |
Arrays cannot be passed as parameters — pass
COPYOF a(read-only) or use a global array. See Language Basics.
Built-in functions¶
Text
| Function | Returns |
|---|---|
LENGTH(s) |
Length of s |
UPSHIFT(s) |
Uppercase copy |
DOWNSHIFT(s) |
Lowercase copy |
instr(s, sub) |
Position of sub in s (0 if absent) |
s[a,b] |
Substring from position a to b |
s CLIPPED |
s with trailing spaces removed |
ASCII n |
The character for code n |
Numeric
| Function | Returns |
|---|---|
ABS(x) |
Absolute value |
ROUND(x, n) |
Rounded to n decimals |
TRUNC(x, n) |
Truncated to n decimals |
x MOD y |
Remainder of x / y |
Date and time
| Function | Returns |
|---|---|
TODAY |
Current date |
CURRENT |
Current date and time |
YEAR(d) MONTH(d) DAY(d) |
Parts of a date |
WEEKDAY(d) |
Day of week (0 = Sunday) |
MDY(m, d, y) |
Build a date from month, day, year |
d + n |
n days after date d |
d2 - d1 |
Number of days between two dates |
Formatting (the USING clause)
LET text = amount USING "###,##&.&&" -- 1,234.50
LET text = order_date USING "yyyy-mm-dd" -- 2026-12-31
System and program
| Function | Returns |
|---|---|
NUM_ARGS() |
Number of command-line arguments |
ARG_VAL(i) |
The i-th command-line argument |
fgl_getenv("VAR") |
Value of an environment variable |
(Function and keyword names are case-insensitive.)
Reports¶
4GL has a built-in report writer for text/printed output. The shape:
REPORT customer_listing(r)
DEFINE r RECORD LIKE customers.*
FORMAT
PAGE HEADER
PRINT "Customer Listing"
ON EVERY ROW
PRINT r.id USING "#####", " ", r.name CLIPPED
PAGE TRAILER
PRINT "End of page ", PAGENO USING "###"
END REPORT
Drive it from your code:
START REPORT customer_listing TO "customers.txt" -- or TO PRINTER, or TO PIPE "..."
FOREACH c_cust INTO rl_cust.*
OUTPUT TO REPORT customer_listing(rl_cust.*)
END FOREACH
FINISH REPORT customer_listing
| Statement | Purpose |
|---|---|
START REPORT r TO dest |
Begin a report (file / PRINTER / PIPE) |
OUTPUT TO REPORT r(row) |
Send one row to the report |
FINISH REPORT r |
End the report |
PRINT … |
Emit a line (inside FORMAT) |
SKIP n LINE[S] |
Blank lines |
System statements¶
| Statement | Purpose |
|---|---|
RUN "command" |
Run a shell command (waits for it) |
RUN "command" WITHOUT WAITING |
Run without waiting |
SLEEP n |
Pause for n seconds |
EXIT PROGRAM [n] |
End the program with optional exit code |
Stored procedures (SPL)¶
SPL (Stored Procedure Language) runs inside the database. You create procedures and functions, then call them from 4GL.
-- defined and stored in the database:
CREATE FUNCTION credit_limit(cust_id INTEGER) RETURNING DECIMAL(10,2)
DEFINE l DECIMAL(10,2);
SELECT limit INTO l FROM customers WHERE id = cust_id;
RETURN l;
END FUNCTION
| Statement | Purpose |
|---|---|
CREATE PROCEDURE … END PROCEDURE |
Define a stored procedure |
CREATE FUNCTION … RETURNING t … END FUNCTION |
Define a stored function |
EXECUTE PROCEDURE p(args) [INTO v] |
Run a stored procedure from 4GL |
EXECUTE FUNCTION f(args) INTO v |
Run a stored function from 4GL |
RAISE EXCEPTION n, 0, "message" |
Raise an error inside SPL |
ON EXCEPTION … END EXCEPTION |
Handle errors inside SPL |
SPL exception handling (
ON EXCEPTION) is for SPL code only. In ordinary 4GL there is noTRY/CATCH— checkSQLCA.SQLCODE(see below).
Status and error variables¶
| Variable | Meaning |
|---|---|
SQLCA.SQLCODE |
Result of the last SQL statement: 0 ok, 100 not found, <0 error |
SQLCA.SQLERRD[3] |
Number of rows processed by the last statement |
STATUS |
Result of the last non-SQL operation |
INT_FLAG |
Set when the user cancels an INPUT / MENU |
SELECT name INTO l_name FROM customers WHERE id = 101
IF SQLCA.SQLCODE = 0 THEN
DISPLAY l_name CLIPPED
ELSE
DISPLAY "Not found"
END IF
For the command-line tools that compile and analyse this code, see Command-line Tools. For the condensed cheat-sheet, see Quick Reference.