Article

Row Identifiers, RECID and ROWID Explained

« Go Back

Information

 
Article Number000001685
EnvironmentProduct: Progress
Version: 8.x, 9.x
Product: OpenEdge
Version: All Supported Versions
OS: All Supported Platforms
Question/Problem Description
Row Identifiers, RECID and ROWID and how Progress can retrieve rows explained.
What is a Row Identifier?
What is the difference between a RECID and a ROWID?
How does Progress uses ROWID to retrieve records?
How does Progress uses RECID to retrieve records?
What is the default index comprised of?
Steps to Reproduce
Clarifying Information
Error Message
Defect/Enhancement Number
Cause
Resolution
To understand how Progress retrieves rows, it is important to understand what row identifiers are and how they are used as part of an index.

A "rowid" is a row identifier that uniquely identifies that row (or data record) in a database.  As soon as a row is created, a row identifier is assigned to it and stays the same for the row's entire life. Even when the primary index key values are changed, the ROWID or the record remains the same. Once a row is deleted, a new row will re-use the rowid identifier. Likewise, deleting and re-creating a row can result in the row getting a new ROWID as will a dump and load.

A RECID is a 32-bit/64-bit positive integer which contains an encoding of the storage address of a record within a Progress database storage area. Recid's can be converted to integers and vice versa. A RECID is essentially a pointer to the first record fragment of the record.  OpenEdge 10.1B introduced 64-bit keys to allow for more records per storage area. For further information see Article 000044869, When does the 2 billion rowid limit per Storage Area apply?   

A ROWID is a variable-length identifier whose semantics and length vary depending on the database type. 
For OpenEdge databases, it is a hexadecimal representation of the RECID and was introduced in Progress 8.  ROWID's are not integers. They are variable length binary strings which cannot be converted to integers, except by chicanery.  ROWID's and RECID's are not interchangeable in ABL code even when they are converted to integers. For further information refer to Article 000001594, 4GL. How to convert a ROWID to a RECID and Vice Versa  

ABL Temp-tables follow the same rules as the OpenEdge database, as for the most part they use the same storage mechanisms.

For foreign databases accessed through a DataServer, the ROWID is a representation of the foreign database's rowid implementation. RECID's are too small to hold Oracle ROWID values and similar constructs in other data managers.

The distinction between RECID and ROWID only applies in ABL. In Progress/OpenEdge SQL, the value returned by the ROWID function is the one referred to here as RECID. When using the getValue() function in a stored procedure or trigger, it should be retrieved as an INTEGER into a Java Integer object. The value referred to here as ROWID is not used in Progress/OpenEdge SQL. 

In order for Progress to retrieve any row efficiently, it needs its row identifier.  These are located via the table's indexes, which will store the index key(s) and for every key a list of row identifiers for the records that contain that key field. When no index is added to a table, Progress automatically creates a default primary index in the Schema Area with the row identifier as its component.  Essentially the default index is a unique index on the row identifier. As soon as an index is added to the table’s schema, the default index is deleted.

If the row identifier is already known reading the index can be skipped, which can often be used to access a record faster.  This is done by using the RECID/ROWID function in the query's WHERE clause, example: 
FIND FIRST CUSTOMER WHERE ROWID(CUSTOMER) = cust-rowid-variable.

For Progress databases, while a record's ROWID never changes during the lifetime of a record, the ROWID only lasts as long as the record does. If the record gets deleted the ROWID becomes available for re-use for another new record. And if that record is then re-created there is no guarantee it will get the same ROWID.  

For DataServer environments the rules depend on the foreign database implementation. The safe assumption is that over longer periods of time the ROWID can change as well.  Therefore as best practice the ROWID values can be used within a single session, but should not be stored beyond that session, The first read of a record should always be by it's key fields in the data to fetch the current ROWID for the session.

With the implementation of table partitioning in OpenEdge 11.4:

RECID can no longer be used to uniquely reference data in a partitioned table as they do not contain a partition-Id component and always pertain to partition 0. 
The existing ROWID information plus the table number is no longer sufficient to uniquely identify a specific record in the database.  
Uniqueness is obtained by also including the partition id associated with the record.  
The internal format of a ROWID has been extended to include the partition information.  
The information associated with a RECID only contains the encoded block and record within block information.
An example is provided in Article: 000047328, How to recover records in a damaged partitioned table     

Implementation of the ROWID representation may be different in future releases, also depending on database type. The changes would not affect functionality but would be aimed at improving performance and scalability
Workaround
Notes
Attachment 
Last Modified Date11/21/2018 11:01 AM
Disclaimer

The origins of the information on this site may be internal or external to Progress Software Corporation (“Progress”). Progress Software Corporation makes all reasonable efforts to verify this information. However, the information provided is for your information only. Progress Software Corporation makes no explicit or implied claims to the validity of this information.

Any sample code provided on this site is not supported under any Progress support program or service. The sample code is provided on an "AS IS" basis. Progress makes no warranties, express or implied, and disclaims all implied warranties including, without limitation, the implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample code is borne by the user. In no event shall Progress, its employees, or anyone else involved in the creation, production, or delivery of the code be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample code, even if Progress has been advised of the possibility of such damages.



Feedback
 
Was this article helpful?

   

Your feedback is appreciated.

Please tell us how we can make this article more useful. Please provide us a way to contact you, should we need clarification on the feedback provided or if you need further assistance.

Characters Remaining: 1025