There is no native ABL function that converts ROWID variables to RECID variables or visa versa. One must exercise caution when trying to convert a RECID to a ROWID, as the converted ROWID value may not always identify the current database record if it doesn't contain all of the information as the record's ROWID.
ROWIDs
- A ROWID is a unique internal identifier of the current database record.
- A ROWID may be converted to a character string representation of the ROWID value using the STRING function.
- A ROWID value converts to a hexadecimal string of the form "0xhexdigits," where hexdigits is any number of characters "0" through "9" and "A" through "F"
- The TO-ROWID Function converts a string representation of a valid ROWID to a valid ROWID value. Although TO-ROWID converts a properly formatted string to a ROWID value, there is no guarantee that this value corresponds to an existing record in your database.
RECIDs
- A RECID is a unique internal identifier of the current database record, which is supported mainly for backward compatibility.
- For most applications, Progress recommends the use of ROWID to identify existing records in a table. A RECID variable has a default INTEGER type representation and may be only part of the ROWID value.
- With the implementation of the Table Partitioning feature 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 RECID 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(4 digits at the end of the ROWID). The information associated with a RECID only contains the encoded block and record within block information. For further information refer to Article:
In the below code, the HexToInt function converts a ROWID to a RECID, and also returns the Partition Id of the record. If 0 is returned for the Partition Id, this indicates that the record is not in a partitioned table.
The IntToHex function converts a RECID and a Partition Id (if available) to a ROWID. If 0 is passed to the Partition Id field, it is assumed the record is not in a partitioned table.
NOTE: When working with 32Bit RECIDs, change the below INT64 variables, parameters and return types to INTEGER.
FUNCTION HexToInt RETURNS INT64
( INPUT pcRowid AS CHARACTER,
OUTPUT piPartition AS INTEGER ):
DEFINE VARIABLE iRecid AS INT64 NO-UNDO INITIAL 0.
DEFINE VARIABLE iChar AS INTEGER NO-UNDO.
DEFINE VARIABLE iCode AS INTEGER NO-UNDO.
DEFINE VARIABLE iExp AS INT64 NO-UNDO.
/* Strip the leading 0x from the ROWID value */
IF pcRowid BEGINS "0x" THEN
pcRowid = SUBSTRING(pcRowid,3).
IF LENGTH(pcRowid) GT 16 THEN
ASSIGN piPartition = INTEGER(SUBSTRING(pcRowid,17))
pcRowid = SUBSTRING(pcRowid,1,16).
ELSE piPartition = ?.
pcRowid = CAPS(pcRowid).
DO iChar = 1 TO LENGTH(pcRowid):
IF CAN-DO("0,1,2,3,4,5,6,7,8,9",
(SUBSTRING(pcRowid, iChar, 1))) THEN
ASSIGN iRecid = iRecid + INTEGER(SUBSTRING(pcRowid, iChar, 1)) *
EXP(16, (LENGTH(pcRowid) - iChar)).
ELSE
ASSIGN iRecid = iRecid + (KEYCODE(SUBSTRING(pcRowid,iChar,1)) -
KEYCODE("A") + 10) * INT64(EXP(16, LENGTH(pcRowid) - iChar)).
END.
RETURN iRecid.
END FUNCTION.
FUNCTION IntToHex RETURNS CHARACTER
( /* RECID to ROWID conversion */
INPUT piRecid AS INT64,
INPUT piPartId AS INTEGER ):
DEFINE VARIABLE cRowid AS CHARACTER NO-UNDO.
DEFINE VARIABLE iRemainder AS INTEGER NO-UNDO.
DEFINE VARIABLE iAsc AS INTEGER NO-UNDO.
ASSIGN /*piPartId = (if piPartId EQ ? THEN 0 ELSE piPartId)*/
iAsc = ASC("a").
DO WHILE TRUE:
ASSIGN iRemainder = (piRecid MOD 16)
cRowid = (IF iRemainder LT 10 THEN
STRING(iRemainder)
ELSE
CHR(iAsc + iRemainder - 10)) +
cRowid.
IF piRecid LT 16 THEN
LEAVE.
piRecid = (piRecid - iRemainder) / 16.
END.
iRemainder = (16 - LENGTH(cRowid)).
DO piRecid = 1 TO iRemainder:
cRowid = "0" + cRowid.
END.
cRowid = "0x" + cRowid.
IF piPartId NE ? AND
piPartId GE 0 THEN
cRowid = cRowid + STRING(piPartId,"9999").
RETURN cRowid.
END FUNCTION.
DEFINE VARIABLE iRecId AS INT64 NO-UNDO.
DEFINE VARIABLE cRowId AS CHARACTER NO-UNDO.
DEFINE VARIABLE rRowID AS ROWID NO-UNDO.
DEFINE VARIABLE iPartitionId AS INTEGER NO-UNDO.
FIND FIRST Customer NO-ERROR.
cRowId = STRING(ROWID(Customer)).
iRecId = HexToInt(INPUT cRowId, OUTPUT iPartitionId).
/* This may not be successful if the table is partitioned because it's
not using the Partition Id. */
FIND Customer WHERE RECID(Customer) = iRecId NO-ERROR.
MESSAGE NAME iRecId SKIP
"Do the ROWIDs match from HexToInt function? "
(IF NOT AVAILABLE Customer THEN FALSE
ELSE cRowid EQ STRING(ROWID(Customer)))
VIEW-AS ALERT-BOX INFO BUTTONS OK.
cRowid = IntToHex(iRecid,iPartitionId).
FIND Customer WHERE ROWID(Customer) EQ TO-ROWID(cRowid) NO-ERROR.
MESSAGE "Do the RECIDs match from the IntToHex function? "
(IF NOT AVAILABLE Customer THEN FALSE
ELSE iRecid EQ INT64(RECID(Customer)))
VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.
Note: 000001594.zip includes example code modifying the above code for running on 32-bit or 64-bit systems.