Microsoft KB Archive/195405

= FIX: A corrupted record may be added to the view if you set focus to the grid every time that a record is added in Visual FoxPro for Windows 3.0 and in Visual FoxPro for Windows 5.0 =

Article ID: 195405

Article Last Modified on 3/10/2005

-

APPLIES TO


 * Microsoft Visual FoxPro 3.0 Standard Edition
 * Microsoft Visual FoxPro 3.0b Standard Edition
 * Microsoft Visual FoxPro 5.0 Standard Edition
 * Microsoft Visual FoxPro 5.0a

-



This article was previously published under Q195405



SYMPTOMS
Use a grid control, which has a local view as its RecordSource. When the base table for the view calls a function for default value of its key field, if you repeatedly add records to the view, and set focus to the grid each time a record is added to force the grid to refresh, you may find a corrupt extra record added to the view. The corrupted record contains nulls (ASCII 0 characters) or spaces.



STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been corrected in Visual FoxPro 6.0.



Steps to Reproduce Behavior
  To create the data, run the following code from a program (.prg) file. This program makes a DBC, a table, and a local view based on the table. CLOSE DATA ALL CREATE DATABASE 'TESTDB.DBC'

CREATE TABLE 'testtab' NAME 'testtab' ; (PK C(5) NOT NULL DEFAULT newid, ;        F1 C(5) NOT NULL)

CREATE SQL VIEW "v_testtab" ; AS SELECT * FROM testdb!testtab

=DBSetProp('V_TESTTAB', 'View', 'UpdateType', 2) =DBSetProp('V_TESTTAB', 'View', 'WhereType', 3) =DBSetProp('V_TESTTAB', 'View', 'SendUpdates', .T.) =DBSetProp('V_TESTTAB', 'View', 'Tables', 'testdb!testtab') =DBSetProp('V_TESTTAB.pk', 'Field', 'KeyField', .T.) =DBSetProp('V_TESTTAB.pk', 'Field', 'Updatable', .F.) =DBSetProp('V_TESTTAB.pk', 'Field', 'UpdateName',     'testdb!testtab.pk') =DBSetProp('V_TESTTAB.pk', 'Field', 'DataType', "C(5)") =DBSetProp('V_TESTTAB.f1', 'Field', 'KeyField', .F.) =DBSetProp('V_TESTTAB.f1', 'Field', 'Updatable', .T.) =DBSetProp('V_TESTTAB.f1', 'Field', 'UpdateName',     'testdb!testtab.f1') =DBSetProp('V_TESTTAB.f1', 'Field', 'DataType', "C(5)")   To demonstrate the behavior, run the following code from a program (.prg) file: * Set the number of iterations #DEFINE NREPS 100 SET ASSERT ON     PUBLIC oform1 SET MULTILOCKS ON     CLOSE DATABASE ALL * Open the view USE testdb!v_testtab * Set the buffering =CURSORSETPROP('buffering',5,'v_testtab') =CURSORSETPROP('buffering',1,'testtab') oform1=CREATEOBJECT("form1") oform1.SHOW RETURN

DEFINE CLASS form1 AS FORM CAPTION = "Form1"

ADD OBJECT cmdbase1 AS COMMANDBUTTON WITH ; TOP = 214, ; LEFT = 146, ; HEIGHT = 27, ; CAPTION = "Run Test", ; NAME = "Cmdbase1"

ADD OBJECT grid1 AS GRID WITH ; HEIGHT = 182, ; LEFT = 25, ; RECORDSOURCE = "v_testtab", ; TOP = 24

PROCEDURE cmdbase1.CLICK LOCAL lnSelectedTab,lcGridAlias, lnCount, lnCnt, lni, retval, ; lnCnt2 FOR lnCount=1 TO NREPS lnSelectedTab=SELECT SELECT v_testtab lnCnt=RECCOUNT('v_testtab') FOR lni = 1 TO 5 APPEND BLANK REPLACE f1 WITH SUBSTR(SYS(3),4,5) * Remove the following line and the error goes away THISFORM.grid1.SETFOCUS ENDFOR lncnt2 = RECCOUNT('v_testtab') SELECT v_testtab retval1=TABLEUPDATE(.T.) * Compare RECCOUNT of view to RECCOUNT before TABLEUPDATE. * If they disagree, the behavior has occurred. ASSERT RECCOUNT('v_testtab')=lnCnt2 MESSAGE ; 'Changed after update' SELECT (lnSelectedTab) * Works with setfocus here instead * thisform.grid1.setfocus ENDFOR ENDPROC ENDDEFINE

* Generic Newid function to make new ID values. FUNCTION NewID LOCAL lcAlias, lnLastID, lcOldReprocess, lnOldArea lnOldArea = SELECT lcAlias = UPPER(ALIAS) lcOldReprocess = SET('REPROCESS') SET REPROCESS TO AUTOMATIC IF USED('IDTable') SELECT IDTable ELSE SELECT 0 IF FILE('IDTable.dbf') USE IDTable ELSE CREATE TABLE IDTable (TableAlias c(50), LastID N(10)) INDEX ON UPPER(TableAlias) TAG TableAlias ENDIF ENDIF

LOCATE FOR ALLT(UPPER(lcAlias))==ALLT(UPPE(TableAlias)) IF !FOUND APPEND BLANK REPLACE TableAlias WITH UPPER(lcAlias) REPLACE LastID WITH 0 ENDIF IF RLOCK REPLACE IDTable.LastID WITH IDTable.LastID + 1 lnLastID = IDTable.LastID UNLOCK ENDIF SELECT (lnOldArea) SET REPROCESS TO lcOldReprocess RETURN PADL(ALLT(STR(lnLastID)),5,'0') ENDFUNC  Click the Run Test command button. When the view record count changes after the TABLEUPDATE, the assert dialog box is displays. This indicates the corruption occurred. Press the Cancel button in the assert dialog box. If you have difficulty reproducing this, you may need to increase the iterations by changing the 100 in the line #DEFINE NREPS 100 to a larger number like 150 or 200.

Look at the last record in the grid. There will be a record under the record where the highlight appears. The extra record contains ASCII 0 characters, and may appear as square boxes or vertical bars. You may have to scroll the grid by clicking the grid's vertical scrollbars down arrow once to make the extra record visible.

If you remove or comment the first THISFORM.grid1.SETFOCUS line in the cmdbase1.CLICK procedure, and uncomment the second SETFOCUS line near the end of the same procedure, the extra record is not added.

If you modify the view, and place the Default Value on the view field as well as the base table field, and then make the view field updateable, the extra record will is not added.

