Feedback
 
Did this article resolve your question/issue?

   

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

 


Article

How to recover records in a damaged partitioned table

« Go Back

Information

 
Article Number000047328
EnvironmentProduct: OpenEdge
Version: 11.4
OS: All supported platforms
Other: Table Partitioning
Question/Problem Description
How to recover records in a damaged partitioned table?
 
Database is damaged and some of the records can not be accessed causing binary dump to fail at that point.

Potentially an index is damaged and/or there is damage to the data block preventing records beyond the damage point from being accessed other than by direct access, using the dump/export by recid mechanism restarting with the recid in the next block when a non-continuable error is found. How can this be fixed ?

RECID cannot be used to reference data in a partitioned table.
 
Steps to Reproduce
Clarifying Information
Damaged index and/or data block partitioned table preventing records beyond the damage point from being accessed except by direct access, by RECID or ROWID.

RECIDs do not contain a partition-Id component and always pertain to partition 0.
Cannot use RECID to reference data in a partitioned table.

The execution of the following code against a partitioned table will not find any records: 
maxRecid = 9223372036854775807.
DO ix = 1 TO maxRecid:
 FIND <tablename> WHERE RECID(<tablename>) = ix.
  IF AVAILABLE(<tablename>)
  EXPORT <tablename>.
END.
Error Message
Defect/Enhancement Number
Cause
Resolution
With the implementation of table partitioning in OpenEdge, the current 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 ABL class can generate all possible ROWID values for any or all partitions for a particular partitioned table. The ABL class is called RowidGenerator.cls . The Rowids class has no built package,  to create one modify the .cls file and store it in the package-specific directory.

The class contains two static methods as follows:

METHOD PUBLIC STATIC VOID TableStart
(tableName AS CHAR,
      startId AS INT64,
      maxId AS INT64,
      partitionId AS INT)

To dump the specific records, call the method TableStart for each table using the following parameters:

tableName - the name of the table
startId - the minimum/starting ROWID value to be returned.
maxId - the maximum/ending ROWID value to be returned.
partitionId - to iterate across a range of rowids for a particular table:
To only dump the records from a single partition for this table, a specific partition Id can be passed using this parameter. 
To dump all records for each defined partition of the table, pass the Unknown value

The code assumes that it is possible to access the _Partition-Policy and _Partition-Policy-Detail records.

METHOD PUBLIC STATIC ROWID GetNextRowid()

Run the code below after each call to TableStart to call GetNextRowid repeatedly until it returns an Unknown value. If there is a record that matches this ROWID, the code exports it so that it can be re-loaded into a new database.
 
DEFINE VARIABLE rid AS ROWID NO-UNDO.

Rowids:TableStart("<tablename>", 1408, 3000, ?).
rid = Rowids:GetNextRowid().

DO WHILE rid <> ?:
    FIND <tablename> WHERE ROWID(<tablename>) = rid NO-ERROR.   
        IF AVAILABLE(<tablename>) THEN DO:
            EXPORT <tablename>.
        END.
    rid = Rowids:GetNextRowid().
END.
 

 

Workaround
The class is needed for partitioned tables. It can be used for a non-partitioned table though using the RECID code shown in the overview would be more efficient.  If this class is used for a non-partitioned table, it is possible to get the template record of the table, normally is not accessible by the ABL.  To avoid dumping this record out and treating it like part of the data, run the following code:
 
DEFINE VARIABLE id AS RECID.

FIND _File WHERE _file-name = "<tablename>".
id = _file._Template.
    <Then once a record is found…>

If NOT RECID(<tablename>) = id THEN
    EXPORT <tablename>.

 
Notes
References to Other Documentation: 

Rowids and Table Partitioning; https://community.progress.com/community_groups/openedge_development/f/19/t/9225.aspx?
Attachment
Last Modified Date6/23/2015 12:21 PM