Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tables: @Structure, @Fields, @Indexes

A table .warp file describes a DDS physical file: its columns and its keyed access paths. It’s referenced from a Program/Screen via @References/Tables.

1. Minimal file

@Properties {
    Type : "Table"
}
@Structure {
    Name        : "GRIDDEMO"
    Description : "Sample customers"
    @Fields {
        CustCode char(6)   Description("Customer code")
        Name     char(20)  Description("Name")
        City     char(15)  Description("City")
    }
    @Indexes {
        PrimaryKey ( GRIDDEMOPK, [CustCode] )
        Index ( GRIDDMNOM, [Name] )
    }
}
  • @Fields: one Name type(...) line per column. Only char/number/date — see Data types. Available modifiers: Description(...), Default(...), AllowNull.
  • @Indexes: PrimaryKey (required, its fields can’t be AllowNull), Unique, Index — each one as Kind(Name, [Field, ...], "optional description").

2. Referencing it from a Program

@References {
    Tables = ["../tables/TLGRIDDEMO.warp"]
}

The path is relative to the file that references it. Once referenced, its fields become available as bare identifiers inside a For Each/New (see below), and as field(FieldName) in @Variables to inherit its type.

3. Reading rows: For Each In

@Source {
    For Each In GRIDDEMO Index GRIDDMNOM
    Where CustCode = &VCustCode
        &VName = Name
        &VCity = City
    When None
        Message("Customer not found", Error)
    EndFor
}

Index picks the access path (defaults to the sequential-access one if omitted); Where filters by equality; When None runs if no row was found.

Joining tables: Join In

To read data from a related table, add Join In under the For Each. The joined table is read by its PrimaryKey for each iterated row:

For Each In Orders
Join In Customers On CustCode = CustCode
    &VName = CustName
EndFor

Without On, the key columns of the joined table must exist with the same name in the iterated table. If there is no match, the row is not skipped and the joined fields are blank or zero. They are read-only. Full details in @Source: control statements.

4. Inserting rows: New

@Source {
    New In GRIDDEMO
        CustCode = &VCustCode
        Name     = &VName
        City     = &VCity
    When Duplicate
        Message("That code already exists", Error)
    EndNew
}

When Duplicate runs if the row already exists: the New looks it up by the table’s PrimaryKey (which must be in @Indexes) and, if found, runs the block on that row and updates it if the block assigned fields. The block accepts any statement (If, While, Do Case, etc.). Details in @Source: control statements.

5. Extended documentation

A table can also carry @Documentation (nested inside @Structure, unlike a Program where it goes at the top level) with @Author, @Application, @Module, @Repository and @History (@Creation + @Change per changelog entry) — see @Structure, @Fields, @Indexes for the full detail of each sub-section.

6. Reverse engineering from an existing DDS

If the table already exists on the IBM i, there’s no need to write it by hand: the WaRPGate: Reverse Engineer command in the VSCode extension connects to the IBM i, reads the DDS (and optionally its associated LFs as @Indexes) and generates the corresponding .warp file. If the record format of the downloaded DDS differs from the table name, Record Format : "X" is written; if it is the same, it is omitted.

DDS comments (lines with * in column 7) are kept too: the file header ones become // lines above @Structure, and those preceding a group of fields become // lines right before the group’s first field. Decorative asterisk borders are left out.