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: oneName type(...)line per column. Onlychar/number/date— see Data types. Available modifiers:Description(...),Default(...),AllowNull.@Indexes:PrimaryKey(required, its fields can’t beAllowNull),Unique,Index— each one asKind(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.