FIX: Corrupt Record Added in Grid Using View with Default Value
ID: Q195405
|
The information in this article applies to:
-
Microsoft Visual FoxPro for Windows, versions 3.0, 3.0b, 5.0, 5.0a
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.
MORE INFORMATIONSteps 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.
REFERENCES
(c) Microsoft Corporation 1998. All Rights Reserved. Contributions by Jim
Saunders, Microsoft Corporation
Additional query words:
Keywords : kbDatabase kbVFp300bbug kbVFp500abug kbVFp600fix KbDBFDBC
Version : WINDOWS:3.0,3.0b,5.0,5.0a
Platform : WINDOWS
Issue type : kbbug
|