Progress KB - How to recover records in a damaged partitioned table




Feedback
Did this article resolve your question/issue?

   

Article

How to recover records in a damaged partitioned table

« Go Back

Information

 
TitleHow to recover records in a damaged partitioned table
URL Name000047328
Article Number000167273
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?
Last Modified Date6/23/2015 12:21 PM
Attachment 
Files Rowids.cls
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.