Defining a temporary record layout

!record

Define a temporary record layout


Syntax

!record record_id [[dim1 [,dim2 [,dim3 [,dim4]]]]] [= structure_id [distinct]] [{
field_id1, [”heading”], type & size [[dim1 [,dim2 [,dim3 [,dim4]]]]] [/logical] [, “format” [,flags [, “validation”]]]
field_id2, [”heading”], type & size [[dim1 [,dim2 [,dim3 [,dim4]]]]] [/logical] [, “format” [,flags [, “validation”]]]
!record subrecord_id [[dim1 [,dim2 [,dim3 [,dim4]]]]] [= substructure_id [distinct]] [{
}]
}]

Define a structured, temporary record layout. The fields of the layout are accessed as record_id.field_id. The scope is the entire program.

record_id

The record structure’s identifying name. Normal identifier naming rules apply.

[= structure_id]

If this clause is present, the record structure is copied from the structure named, which can be a file or record. See Record structure copied from a file or record.


Record structure field list

No structure_id clause.

If the structure_id is not present, then a field list for the structure of the record buffer may be provided. The field list items are composed as follows:

field_id

The individual name of the field. It is referred to by using the structure record_id.field_id. That is, the field called “mouse” in the layout whose record_id is “rodents” is known as “rodents.mouse”. Fields in different layouts may therefore be given the same name without confusion arising.

heading

The default heading to be used if the field is displayed on the screen or printed. Must be enclosed in quotes. Two consecutive commas at this point cause the field_id to be used as the heading.

type & size

Any valid Sculptor data type.

dim

The number of subscripts the field is to have, in up to four dimensions. The subscripts are enclosed in square brackets, with each dimension separated by commas.

logical

Defines the field as a special logical type, such as date or time.

format

A template controlling the specific format to be used for input, display and printing of this field. The format must be enclosed in quotes. Two consecutive commas indicate that no special format is required, in which case the default for the field type and size will be used.

flags

One or more flag characters indicating more general formatting operations. Flag characters are not enclosed in quotes. Two consecutive commas indicate that no flags are required.

validation

A validation list indicating the acceptable values for input into the field. Optional.

See Structure of a data field for more information.


Record structure subrecord

Since Sculptor version 6.2.0

If the structure_id is not present, then a subrecord structure of the record buffer may be provided. The syntax is exactly the same as a normal !record. It may also contain other subrecords, fields or a mix of them.

These are the features, options and limitations of the subrecords:

  • Records can be defined inside records with a maximum of 256 nested levels

  • The subrecords can be normal defined !records or copy records (!record rec1 = rec2)

  • An entire nested record or subrecord can be copied (it will include all the nested child records)

  • The nested records fields can be referenced with shorter names as long as there is no ambiguity

  • References (using copy records) between nested records are supported as long as they are not cyclic

The nested record feature makes possible to handle nested objects in:

EXAMPLES

  • Normal nested !record:

    !record nestedRec {
        fld,,i4
        !record subRec {
            fld,,i4
            !record subSubRec {
                subSubFld,,i4
            }
        }
    }
    
    /* INCORRECT field references (Ambiguity) the compiler will complain */
    fld = 1
    
    /* Correct field references */
    nestedRec.fld = 1
    
    subRec.fld = 1
    nestedRec.subRec.fld = 1
    
    subSubFld = 1
    subSubRec.subSubFld = 1
    subRec.subSubRec.subSubFld = 1
    nestedRec.subRec.subSubRec.subSubFld = 1
    
  • Nesting copy records:

    !file FILE1
    !file FILE2
    !record rec1 {
        fld,,i4
    }
    !record anotherNestedRec {
        !record subRec {
            fld,,i4
        }
    }
    
    !record nestedRec {
        fld,,i4
        !record FILE1 = FILE1
        !record AnotherFILE1 = FILE1
        !record File2 = FILE2
        !record subRec1 = rec1
        !record nestedSubRec = anotherNestedRec
    }
    
    /* Some examples of field access */
    nestedRec.nestedSubRec.subRec.fld = 1
    nestedRec.subRec1.fld = 1
    
  • Cross references:

    !record nested1 {
        !record subRec1 {
            fld,,i4
        }
        !record subRec2 = nested2.subRec2
    }
    !record nested2 {
        !record subRec1 = nested1.subRec1
        !record subRec2 {
            fld,,i4
        }
    }
    

Record structure copied from a file or record

If the structure_id clause is present, then the temporary record structure is identical to a record structure already defined or declared. The structure_id may be either:

1

The file_id of a file declared in the program by use of the ![o]file command.

2

The record_id of another temporary record structure declared in the program by !record. The !record structure from which the fields are copied should be of the type with its own field list (no structure_id clause present).

The temporary record structure is created dynamically at runtime. No field list is required in the !record declaration, as the field list is created automatically by reference to the fields in the named structure. The fields in the temporary record layout are given the same names as their counterparts in the source structure, and are accessed as record_id.fieldname.

Copy records share the data structure and attributes, so that when we resize an array field of a single copy record, we resize all the copy records. As this is not always the desired behaviour Since Sculptor version 6.2.0 we’ve added a distinct flag to the end of the copy record definition to just maintain the origin and destination records distinct and independent.

EXAMPLE

!record OrigRec {
    arrayFld,,i2[10],,a
}

!record CopyRec = OrigRec

!record DistRec = OrigRec distinct

OrigRec.arrayFld->flags = ""
/* Does affect: CopyRec.arrayFld->flags = "" */
/* Does not affect: DistRec.arrayFld->flags = "a" */

redim(DistRec.arrayFld, 1, 20)
/* dim(DistRec.arrayFld, 1) = 20 */
/* Does not affect: dim(OrigRec.arrayFld, 1) = 10 */
/* Does not affect: dim(CopyRec.arrayFld, 1) = 10 */

Record arrays

In Sculptor version 6.2.0 records or subrecords can be defined with up to 4 dimensions.

Notes:

  • An entire or an indexed position of a record array can be assigned.

  • When a record array is referenced without index it means the whole record when applicable, otherwise the first position.

  • Record arrays are not useful when used to identify fields in places where no index can be specified, like in textbox “field” attribute…, as they resort always to index 1.

  • A copy record of a record array is also a record array (both records will always have the same dimension unless copied with the distinct keyword)

  • Record arrays could be redimension with redim() and each dimension can be queried with dim() (like fields)

  • A new dynamic attribute has been added to records (in flags attribute): RECFL_AUTOREDIM to make the record array autoresizeable (by default the record is not autoresizeable).

  • The sort() function now can sort !record arrays.

  • The fromname() function supports record arrays.

  • Pointer fields can point to nested record arrays and even a field array position. Since version 6.2.0 the whole index is stored in the pointer (all the intermediate record indexes included)

  • The functions read_cookie_value() and read_web_values() support record arrays.

  • Support of nested record arrays on <SCFIELD> tag used in “*.sch”, “*.shj” and “*.scx” files.

  • The clear command supports nested record arrays.

  • The table source_object property supports record arrays.

Note

New in version 6.3.8: See the new features.

Added the posibility to define a copy record while changing or setting the dimensions. Note: When doing this the copy record is automatically a distinct copy record.

This new feature permits this kind of code:

!file fileId "SomeFile"

!record fileIdArray[10] = fileId

EXAMPLE

This example defines a two dimension record with two one-dimension subrecords:

!record Rec[2,3] {
    !record subRec1[8] {
        fld,,i4[2]
    }
    !record subRec2 = Rec.subRec1
}
Rec[1,2].subRec2[4].fld[2] = 25
Rec[2,1] = Rec[1,2]

Autoresizeable record flag

The flag RECFL_AUTOREDIM applied to a record array make that record eligible for automatic redimension, which means than in certain cases the dimension sizes of the array will be automatically changed to the assigned value dimension size. The flag must be specified dynamically with the flags attribute Rec->flags = RECFL_AUTOREDIM.

The cases where an array can be adjusted are:

  • When assigning a record(Rec1) to another record(Rec2), when any receiving record or subrecord has the RECFL_AUTOREDIM flag will be redim’ed to the size of the sending record if the sending dimension is larger:

    !record Rec1[10] {
        txt,,a8
        !record SubRec[10] {
            txt,,a8
            num,,i4[2]
        }
    }
    
    !record Rec2[2] {
        txt,,a8
        !record SubRec[2] {
            txt,,a8
            num,,i4[2]
        }
    }
    
    /* Rec2 won't be resized as the autoredim flag is not set */
    Rec2 = Rec1
    
    /* Now Rec2 will be redimed from [2] to [10] but not SubRec before assigned */
    Rec2->flags = RECFL_AUTOREDIM
    Rec2 = Rec1
    
    /* Now SubRec will be redimed from [2] to [10] before assigned */
    Rec2.SubRec->flags = RECFL_AUTOREDIM
    Rec2 = Rec1
    
  • read_json_values, read_xml_values, read_web_json_values, read_web_xml_values and http_simple_send when Reading a JSON or XML file, stream or web content using any of these functions the dimension of any array records defined with the RECFL_AUTOREDIM flag is redim’ed to be the size of the read JSON or XML object array.


Record assignment

Two record buffers (being a !record or a ![o]file) can be assigned one to another. The fastest copy happens when one record is a copy record of the other one, like in !record rec1 = rec2. When that happens just a memory copy is used (as all the fields are the same). Otherwise all fields in the destination record which bear identical field names to fields in the source record are assigned the values (with the standard Sculptor type conversions) while fields that do not match are not updated.

See record buffer assignment for more information/examples regarding the use of records with subscripts, record arrays and nested records in record assignment.


Record runtime reference

Since Sculptor version 6.2.0 a runtime reference is supported to access a !record or ![o]file fields or subrecords when using a pointer or function arguments.


Comparing buffers

The comparison operators:

=

is equal to

<> !=

is not equal to

may be used with file and record buffers. The buffers being compared must have identical structures. All elements of subscripted fields are compared.

The result of comparing non-identical buffers, or using other comparison operators such as < and >, is undefined.

EXAMPLES

  1. Save current data in a record buffer, enabling easy redisplay if dialog cancelled:

    !ofile Sales "data/sales" update
    !record TempSales = Sales
    
         TempSales = Sales
         dialog SalesWin
         ...
    
         switch (tmp.Status) {
              case = CANCEL_DIALOG:
              Sales = TempSales
              Display()
              break
    
         default:
              write Sales
              break
         }
    
  2. Save current data and compare after dialog:

    !ofile Numbers "numbers"
    !record Numbuf2 = Numbers
    
         Numbuf2 = Numbers
         dialog wintask
    
         if (Numbers = Numbuf2){
              info "Data unchanged"
         }
         else {
              write Numbers
              info "Records updated"
         }
    

Runtime attributes

Since Sculptor version 6.2.0 a flags attribute has been added to !record objects. This attribute can be used to define the !record behaviour. See the possible values.

EXAMPLE

!record rec[4] {
    fld,,a4
}

rec->flags = RECFL_AUTOREDIM

RELATED TOPICS

!temp

Data fields

Record buffer assignment

RECFL_ flags

redim()