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.