Skip to content

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

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 DEFINE statements must appear at the top of a function or MAIN, 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 CASE for multi-way branches; avoid ELSE 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.

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 no TRY/CATCH — check SQLCA.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.