Salesforce

4GL/ABL: How to programmatically get a table's number of records per block?

« Go Back

Information

 
Title4GL/ABL: How to programmatically get a table's number of records per block?
URL NameP193773
Article Number000156604
EnvironmentProduct: OpenEdge
Version 10.x, 11.x
Product: Progress
Version: 9.x
OS: All supported platforms
Question/Problem Description
4GL/ABL: How to programmatically get a table's number of records per block?
4GL/ABL: How to programmatically get the block number of a given table record?
4GL/ABL: How to programmatically get the size of a specific table record?
4GL/ABL: How to programmatically get the Area Extent Path of a specific table record?
Steps to Reproduce
Clarifying Information
Error Message
Defect Number
Enhancement Number
Cause
Resolution

The following 4GL/ABL getTableAndRecordInfo.p procedure can be modified to requirement:

  • Accepts a database table name and a table record ROWID as input
  • Returns the table's number of records per block, the block number of the given record, record size and the Area Extent Path of that record
  • The following example code runs against the sports2000 database for all records in the Customer Table
Example: 32;42;1363;130;db\dbname_9.d1
 
DEFINE VARIABLE cDataBaseTableName   AS CHARACTER   NO-UNDO.
DEFINE VARIABLE iNumRecordsPerBlock  AS INTEGER     NO-UNDO.
DEFINE VARIABLE iBlockNumberOfRecord AS INTEGER     NO-UNDO.
DEFINE VARIABLE cAreaExtentPath      AS CHARACTER   NO-UNDO.

ASSIGN
    cDataBaseTableName = "Customer".

FOR EACH Customer NO-LOCK:

  RUN getTableAndRecordInfo ( 
  INPUT cDataBaseTableName,
    INPUT ROWID(Customer),
    OUTPUT iNumRecordsPerBlock,
    OUTPUT iBlockNumberOfRecord,
    OUTPUT cAreaExtentPath
    ).

OUTPUT TO ./TableAndRecordInfo.out APPEND.
            PUT UNFORM iNumRecordsPerBlock ";" iBlockNumberOfRecord ";" RECID(Customer) ";" RECORD-LENGTH(Customer) ";" cAreaExtentPath SKIP.  
OUTPUT CLOSE.
END.

PROCEDURE getTableAndRecordInfo:
/* getTableAndRecordInfo.p */
DEFINE INPUT PARAMETER cDataBaseTableName    AS CHARACTER   NO-UNDO.
DEFINE INPUT PARAMETER rCurrentRecordRowid   AS ROWID       NO-UNDO.
DEFINE OUTPUT PARAMETER iNumRecordsPerBlock  AS INTEGER     NO-UNDO.
DEFINE OUTPUT PARAMETER iBlockNumberOfRecord AS INTEGER     NO-UNDO.
DEFINE OUTPUT PARAMETER cAreaExtentPath      AS CHARACTER   NO-UNDO.

DEFINE VARIABLE cCurrentRecordRowid          AS CHARACTER   NO-UNDO.
DEFINE VARIABLE iLoopCounter                 AS INTEGER     NO-UNDO.
DEFINE VARIABLE iLengthOfRowidString         AS INTEGER     NO-UNDO.
DEFINE VARIABLE dTempDecimalValue            AS DECIMAL     NO-UNDO.
DEFINE VARIABLE dRunningBlockTotal           AS DECIMAL     NO-UNDO.
DEFINE VARIABLE lFixedExtentType             AS LOGICAL     NO-UNDO.

/* Calculate number of records per block for this table area from _Area._Area-Recbits  */
FIND _File WHERE _File._File-Name = cDataBaseTableName NO-LOCK NO-ERROR.
FIND _StorageObject WHERE _StorageObject._Object-Type = 1 AND _StorageObject._Object-Number = _File._File-Num NO-LOCK NO-ERROR.
FIND _Area WHERE _Area._Area-number = _StorageObject._Area-Number NO-LOCK NO-ERROR.
iNumRecordsPerBlock = EXP(2,_Area._Area-Recbits).

/* Calculate block number of the current record */
ASSIGN
    cCurrentRecordRowid  = STRING(rCurrentRecordRowid)
    cCurrentRecordRowid  = REPLACE (cCurrentRecordRowid, '0x', '')
    cCurrentRecordRowid  = CAPS(cCurrentRecordRowid)
    iLengthOfRowidString = LENGTH(cCurrentRecordRowid).

DO iLoopCounter = 1 TO iLengthOfRowidString:
    IF CAN-DO("0,1,2,3,4,5,6,7,8,9", (SUBSTRING(cCurrentRecordRowid, iLoopCounter, 1))) THEN
        ASSIGN
            dTempDecimalValue = dTempDecimalValue + INTEGER(SUBSTRING(cCurrentRecordRowid, iLoopCounter, 1)) * EXP(16, (LENGTH(cCurrentRecordRowid) - iLoopCounter)).
    ELSE
        ASSIGN
            dTempDecimalValue = dTempDecimalValue + (KEYCODE(SUBSTRING(cCurrentRecordRowid, iLoopCounter, 1)) - KEYCODE("A") + 10) * EXP(16, (LENGTH(cCurrentRecordRowid) - iLoopCounter)).
END.
iBlockNumberOfRecord = TRUNC (dTempDecimalValue / iNumRecordsPerBlock, 0).

/* Calculate extent number of current record ( record block) */
FOR EACH _AreaExtent NO-LOCK OF _Area WHERE _Extent-Type = 37:
    dRunningBlockTotal = dRunningBlockTotal + _AreaExtent._Extent-Size * 1024 / _Area._Area-BlockSize.
    IF dRunningBlockTotal GE iBlockNumberOfRecord THEN DO:
        lFixedExtentType = TRUE.
        LEAVE.
    END.
END.
IF  lFixedExtentType THEN
    cAreaExtentPath = _AreaExtent._Extent-path.
ELSE
    DO:
        FIND LAST _AreaExtent OF _Area NO-LOCK.
        cAreaExtentPath = _AreaExtent._Extent-path.
    END.
END PROCEDURE.
 

Alternatively, the following procedure calls the above getTableAndRecordInfo.p procedure to return data about the Customer table and its last record.  This sample procedure provides information about a specific record, the code can be modified to obtain the same data about specific records:

DEFINE VARIABLE cDataBaseTableName   AS CHARACTER   NO-UNDO.
DEFINE VARIABLE iNumRecordsPerBlock  AS INTEGER     NO-UNDO.
DEFINE VARIABLE iBlockNumberOfRecord AS INTEGER     NO-UNDO.
DEFINE VARIABLE cAreaExtentPath      AS CHARACTER   NO-UNDO.

ASSIGN
    cDataBaseTableName = "Customer".

FIND LAST Customer NO-LOCK.
RUN getTableAndRecordInfo.p(
    INPUT cDataBaseTableName,
    INPUT ROWID(Customer),
    OUTPUT iNumRecordsPerBlock,
    OUTPUT iBlockNumberOfRecord,
    OUTPUT cAreaExtentPath
    ).
MESSAGE
    iNumRecordsPerBlock "~n"
    iBlockNumberOfRecord "~n"
    cAreaExtentPath
    VIEW-AS ALERT-BOX INFO BUTTONS OK.
Workaround
Notes
Keyword Phrase
Last Modified Date7/22/2019 9:05 AM

Powered by