FIX: Header Corruption Causes END TRANSACTION to Discard Appended Records (293638)



The information in this article applies to:

  • Microsoft Visual FoxPro for Windows 5.0
  • Microsoft Visual FoxPro for Windows 5.0a
  • Microsoft Visual FoxPro for Windows 6.0
  • Microsoft Visual FoxPro for Windows 7.0

This article was previously published under Q293638

SYMPTOMS

An off-by-one record count in the header of a table may cause the END TRANSACTION command to discard appended records with no error message displayed.

RESOLUTION

If your tables are subject to this type of corruption, use a test as shown below to compare the physical file size to the logical file size. Run this test when you open the table.

STATUS

This bug was corrected in Microsoft Visual FoxPro 8.0.

MORE INFORMATION

Steps to Reproduce the Behavior

  1. Copy the following code into a .prg file and then run it:
    LOCAL nRecCount, nLogicalSize, nPhysicalSize, nHandler, i
    
    CREATE DATABASE test_db
    CREATE TABLE test_tbl (one_field N(1,0))
    FOR i = 1 TO 5
    	INSERT INTO test_tbl (one_field) VALUES (i)
    ENDfor
    
    * Check size before corruption.
    SELECT test_tbl
    nRecCount = RECCOUNT()
    nLogicalSize = HEADER() + (nRecCount * RECSIZE()) + 1
    USE IN test_tbl
    
    nHandler = FOPEN('test_tbl.dbf', 2)
    nPhysicalSize = FSEEK(nHandler, 0, 2)
    FCLOSE(nHandler)
    
    ? 'BEFORE CORRUPTION'
    ? 'Record count: ', nRecCount
    ? 'Logical size: ', nLogicalSize
    ? 'Physical size:', nPhysicalSize
    
    * Manually decrease the record count in the table header.
    * Normally it would happen accidentally after some power 
    * or network failures.
    
    ?
    ? 'Simulating table corruption...'
    nHandler = FOPEN('test_tbl.dbf', 2)
    FSEEK(nHandler, 4)
    FWRITE(nHandler, CHR(4))
    FCLOSE(nHandler)
    
    
    * Check size after corruption
    USE test_tbl
    nRecCount = RECCOUNT()
    nLogicalSize = HEADER() + (nRecCount * RECSIZE()) + 1
    USE IN test_tbl
    
    nHandler = FOPEN('test_tbl.dbf', 2)
    nPhysicalSize = FSEEK(nHandler, 0, 2)
    FCLOSE(nHandler)
    
    ?
    ? 'AFTER CORRUPTION'
    ? 'Record count: ', nRecCount
    ? 'Logical size: ', nLogicalSize
    ? 'Physical size:', nPhysicalSize
    
    
    * I will try inserting a record within a transaction.
    
    ?
    ? 'Inserting new record...'
    
    USE test_tbl
    BEGIN TRANSACTION
    INSERT INTO test_tbl VALUES (6)
    END TRANSACTION
    ? 'No error:', ERROR()
    
    * Check size after insert
    nRecCount = RECCOUNT()
    nLogicalSize = HEADER() + (nRecCount * RECSIZE()) + 1
    
    USE IN test_tbl
    
    nHandler = FOPEN('test_tbl.dbf', 2)
    nPhysicalSize = FSEEK(nHandler, 0, 2)
    FCLOSE(nHandler)
    
    ?
    ? 'AFTER INSERTION'
    ? 'Record count: ', nRecCount
    ? 'Logical size: ', nLogicalSize
    ? 'Physical size:', nPhysicalSize
    
    ? 'VFP discarded insert operation.'
    CLOSE DATA ALL
    					

Modification Type:MinorLast Reviewed:4/24/2003
Keywords:kbbug kbDatabase kbpending KB293638