read

Fetch an occurrence from the hitlist.

read{/lock} %\

{using  Index | options "{index=Index} {;maxhits=n | ALL } {; cache=n | ALL } {;step=n } {;   offset=n} "} %\

{u_where (SelectionCriteria) | where  DMLStatement | u_condition (Condition)} %\

{order by"Field1 {desc}{,FieldN {desc}}"}

Example: read order by "INVOICE_MONTH"

Qualifiers

Qualifiers
Qualifier Description
/lock Locks the occurrence when it is read, if the DBMS supports this feature. See /lock.
usingIndex Specifies the index Uniface should use for record-level DBMSs; ignored for field-level DBMSs. Check the appropriate DBMS connector documentation to verify that the using clause is available for your DBMS.
options Uniface list of performance-related parameters applied when reading from a DBMS.
index Index that Uniface should use for record-level DBMSs; equivalent to the usingIndex clause.
maxhits Maximum number of hits that can be returned by a query. To specify the maximum (which is 32767), use ALL.
cache Maximum size (in bytes) of an occurrence that can be retrieved and placed in the select cache. To specify the maximum, use ALL. In this case, all occurrences that do not have overflow or BLOBs can be retrieved and placed in the select cache.

If field length < n, the complete occurrence is placed in select cache. If the cache size is not specified, the default value is 512 bytes.

step Step size of the query. If not set, the default value is 10.
offset Number of records to be skipped before data reading starts; must be >=0. If specified, you must also specify maxhits and order by. See offset .
u_where Specifies additional criteria by which records are to be read. For more information, see u_where.
where Specifies additional criteria by which records are to be read, using database-specific DMLSelectionCriteria. The database must therefore support some form of DML, such as SQL. See where.
u_condition Provides a DBMS-independent profile for selection. For more information, see u_condition.
order by Specifies one or more fixed-length database fields to use for ordering the selected records. The default sort order is ascending, but it can be set to descending using desc. The specified field names must be unqualified, that is, without the entity and model name. See order by.

Parameters

Parameters
Parameter

Data Type

Description
Index Number Number or numeric expression that evaluates to the index number required.
n Number Number or numeric expression.
SelectionCriteria String Criteria for reading records. One or more relational phrases with the operands linked by relational operators (<, !=, and so on), connected by logical operators (&, |, and so on). The operand to the left of the operator must be a field in an entity; the operand to the right can be a value.
DMLSelectionCriteria String DBMS-specific selection criteria for reading records. Consult your DBMS documentation for the correct syntax.
Condition

String

Conditional statement used as a retrieve profile.

OrderBySpecs

String

Comma-separated list containing one or more specifications of the format:

LiteralFieldName {desc}

Return Values

Values Returned by read in $status
Value Meaning
0 Occurrence was successfully read.
<0 An error occurred. See $procerror for details
Values Commonly Returned by $procerror Following read
Value Error constant Meaning
-1 <UGENERR_ERROR>  
-2 through -12 <UIOSERR_*> Errors during database I/O.
-2 <UIOSERR_OCC_NOT_FOUND> Occurrence or record not found; the table is empty or end of file was encountered. (Usually the table or file is empty.)

The entity is an Up entity and the key value was not found during the database lookup.

This error can also occur if maxhits is set to more than 32767.

-3 <UIOSERR_EXCEPTIONAL> Exceptional I/O error (hardware or software).
-4 <UIOSERR_OPEN_FAILURE> The table or file could not be opened. The entity is not in the component structure or the corresponding table or file does not exist in the database.
-8 <UIOSERR_END_OF_HITLIST> End of hitlist.
-11 <UIOSERR_LOCKED> read/lock only: Occurrence already locked.
-15 <URETERR_MULTIPLE_UP> The entity is an Up entity and multiple hits were found during the database lookup.
-16 through -25

<UNETERR_*>

Errors during network I/O.
-16 UNETERR_UNKNOWN Network error: unknown.
-20 <UNETERR_MAX_CLIENTS> Router could not accept new client, $MAX_CLIENTS exceeded.
-31 <UGENERR_LICENSE> The TRX-formatted DML statement from a where clause exceeds 32 KB.
-37 <IOSERR_OFFSET_NOTSUPPORTED> The offset option was specified but the database connector does not support pagination
-38 <IOSERR_OFFSET_PARAMETERS> order by missing, or incomplete or wrong options for offset.
-403 <UMISERR_UWHERE> Nonexistent field in a u_where clause.
-404 <UMISERR_TRX> The TRX-formatted DML statement from a where clause or an sql statement exceeds 32 KB.

Use

Allowed in all component types.

Description

The read statement should be used only in the read trigger.

The first time that the read trigger is activated for an entity, the read statement is executed, triggering the following actions:

  • The read statement generates a database select statement using any specified read statement parameters, such as such as u_where, where, u_condition, order by and so on.
  • The database builds a hitlist and returns a pointer to that hitlist to Uniface
  • Uniface fetches the first occurrence from the hitlist and activates any field-level formatFromDbms triggers that contain ProcScript.

When the read trigger of the next and subsequent occurrences is fired, other occurrences can be fetched from the hit list on an as-needed basis, without having to start the whole database I/O transaction again. Any read statement parameters, such as u_where and so on are only used on the first read statement. On consequent reads these parameters are ignored.

After the read trigger is activated, $rettype function indicates the type of retrieval request that activated it (such as retrieve or ^Next occurrence). This can be useful for conditional processing. For more information, see $rettype.

Tip: A read statement can be quite long, so use line continuation markers (%\) to improve the readability of the statement.

You can place assignments after the read statement in the read trigger. This is often a good place to initialize non-database fields, but you should first test for success after the read statement. For example:

trigger read
  read
  if ($status == 0)
    ; Populate non-DB field POSTAL_ADDRES:
    POSTAL_ADDRES.ENT = $concat(STREET.ENT, "%%^", CITY.ENT)
  endif
end; 

/lock

The optional /lock switch locks the occurrence when it is read, if the DBMS supports this feature. (This is called paranoid locking.)

Using /lock eliminates the extra read action implicit in the normal lock statement and overrides optimistic locking in any DBMS.

The lock trigger is not activated when the /lock switch is used.

u_where and where

You can use either the u_where clause or the where clause within the same read statement, but not both. Not all databases can handle these clauses; in this situation Uniface itself handles the clause.

  • u_where provides a database-independent way of specifying additional selection criteria. For more information, see u_where.
  • where is database-specific, and the database must support some form of DML, such as SQL, QUEL, or RDO. Consult your DBMS connector documentation to check whether the where clause is supported for your DBMS. For more information, see Data Retrieval Support.

When a u_where or where clause is used on a read statement, all occurrences that match the selection criteria are read. If the entity is an Up entity, the u_where or where clause is considered only if the foreign key is complete and not NULL. These clauses can be used to further restrict the number of occurrences read for the up entity.

These clauses are used in addition to those specified by the user in the retrieve profile entered before the ^RETRIEVE function is activated. For example, the following ProcScript in the read trigger only allows retrieves occurrences where the value of the SALARY field is less than 25000:

trigger read
  read u_where (SALARY < 25000)
end; read

where

The where clause has a DBMS-specific format; consult your DBMS documentation for the correct syntax.

The where clause is inserted into the DML Select statement, which is passed to the connector in Uniface's internal format. This may be double the size of the original DML statement. The data is limited to 32 kilobytes.

Caution: Uniface passes the DML clause as is to the DBMS connector, but it will attempt to do string substitution first. The Uniface %% symbols for the substitution may conflict with the SQL-syntax of the remaining expression.

To prevent such conflicts, prepare the selection profile clause carefully. For example, you want to select records in which FLD1 contains the string abc, using SQL wildcards. You could prepare the profile in several ways.

  • Include SQL wildcards (% symbols) in the profile and use Uniface %% characters in the where clause:
    $Profile$ = "%abc%" 
     retrieve
    trigger read
       read where "FLD1 = %%($Profile$)"
     end
  • Alternatively, use $concat to build up the clause with the correct syntax. The profile clause does not have to handle the %-symbols, as there is no conflict:
    $Profile$ = "abc"  
      retrieve

    Instead, SQL wildcards can be handled by the next line:

    trigger read
       read where $concat("F1 like '%", $Profile$, "%'")
     end

The where clause is not parsed by Uniface because it is DBMS-specific, so it is wise to check the return value of the read statement and, if necessary, the value of $dberror.

Uniface enables you to define subtype entities which reference a common database table, or redirect entities to database tables in the [ENTITIES] section of the assignment file. However, subtypes and entity redirection are not understood by DBMSs.

Caution: When specifying the entity in a where clause, use the name of the database table, not the entity.

offset

Important: The offset option is not supported by all database connectors, so you should consult the connector documentation for your target database before using it. For more information, see Data Retrieval Support.

The offset option makes use of database-specific functionality to specify where to start reading the data. It must be used with the maxhits option and order by clause, making it possible to implement data paging functionality. For example, to start with the 11th record, use offset=10. The following statement fetches 10 records from a dataset that has been order by the BIRTHDATE field , starting at the 101st record:

read options "maxhits=10;offset=100" order by "BIRTHDATE"

The offset option is especially useful in web applications, which cannot use stepped hitlists. (In non-web applications, using offset has no effect on the stepped hitlist mechanism.)

Typically, the value of offset is a variable that holds a calculated number, making it possible to reset the value to retrieve the previous or next set of records (where the set is determined by maxhits). For example, in the following code the offset is calculated using the value of the PAGESIZE field and the requested page number:

trigger read
...
vOffset= PAGESIZE * $vPageNum$
read options "maxhits=%%PAGESIZE%%%·;offset=%%vOffset%%%" order by "LASTNAME"
...
end

During compilation, if the offset= string is detected and there is no order by clause, a warning is issued:

error:   1000 - Syntax error ("order by" missing, or
                            incomplete or wrong options for offset)

At runtime, the read command fails with error -38 if any of the following is conditions apply:

  • offset specifies a negative number
  • maxhits is not specified, is 0, or negative.

    An order by clause is not specified.

Because offset relies on native database paging features, it can have a performance advantage over stepped hitlists. However not all databases have such a feature, so using offset means that your application is no longer database-independent.

For more information, see Example: Using Database Data Paging .

order by

The order by clause specifies a comma-separated list of fields as a string. It determines the ordering sequence of the selected records and is valid for all DBMSs. Each field name provided must be unqualified; for example, you can use the unqualified field name INVAMOUNT, but not the qualified field name INVAMOUNT.INVOICES.

The default ordering is ascending, but you can set it to descending using the desc keyword. For example:

; trigger: Read
read order by "INVOICE_MONTH desc"

However, order by only works on fixed-length fields. Also, you cannot use a field that has been defined as part of an entity but is not stored in the database to sort records in an order by clause. If you require records sorted on such a field, use the sort ProcScript statement.

Caution: The compiler does not flag invalid fields as an error if you attempt it, nor does Uniface check for the existence of the field names in an order by clause. Using an unknown field name can cause unpredictable results in sorting.

If you use an order by clause in combination with a DBMS that does not support ordering, Uniface retrieves and sorts all matching records. This can have a noticeable impact on performance. Additionally, when the component ends, the retrieved data must be dropped from memory. Consequently, the order by clause can affect performance not only for retrieval, but also when exiting the component.

Not all DBMSs support descending sorts, so check the appropriate connector documentation to see if your DBMS supports this feature.

Reading and Sorting Occurrences

The following example reads in occurrences from the component, ordering them by the INVOICE_MONTH field:

; trigger: Read
read order by "INVOICE_MONTH"

Ordering Read Occurrences by a Dynamic Profile

The following example defines the sort profile dynamically. The contents of the dummy field SORT_PROFILE specify by which field to order the occurrences:

operation exec
if ($1="month")
   SORT_PROFILE.DUMMY = "INVOICE_MONTH"
else
   SORT_PROFILE.DUMMY = "INVOICE_AMOUNT"
endif
end; exec
; trigger: Read
read order by SORT_PROFILE.DUMMY

Reading and Sorting Occurrences

The following example uses order by to sort the records read:

trigger read
   $1 = "custnumber desc, invoice_date"
   read order by $1
end; read

read u_where

The following example returns all occurrences of the current entity for which no PAYDATE has been entered:

trigger read
   read u_where (paydate = "") order by "invoice_amount"
end; read

read where

The following example retrieves occurrences of the entity INVOICE which have an INVAMOUNT greater than 100:

;  entity "INVOICES"
trigger read
   read where "INVAMOUNT > 100"
end; read

You may have to qualify the name of the field with the entity name. This qualification is DML-specific.

If you had defined the entity INVOICES in the model as a subtype of the entity TRANSACT, you would have to use the supertype as a qualifier. This is because DBMSs do not recognize subtypes; subtypes are a Uniface feature. The previous example would therefore have to be rewritten as:

;  entity "INVOICES"
trigger read
  read where "TRANSACT.INVAMOUNT > 100"
end; read

You can use the more general u_where clause, which is DBMS-independent. The previous example would then be rewritten as:

;  entity "INVOICES"
trigger read
  read u_where (INVOICES.INVAMOUNT > 100)
end; read
History
Version Change
9.6.01 Added offset option

Related Topics