We recently had the pleasure of working with one of our favourite sorts of client - the type who are enthusiastic about their speciality field and who have trained themselves to program - to allow themselves to write MOST of the system they need to service their enthusiasm. Every now and again, they call us in to do some of the heavy lifting for them.
This particular time the client had an issue with a multi page form. Under most circumstances the data displayed correctly but under - as yet undetermined circumstances - the data display would become corrupt. Data would appear in edit fields that belonged in other edit fields and existing data would be overwritten by seemingly unrelated data.
Approaching the issue logically, we installed break points to ensure that what was read from disk was correct and sure enough @Record and the ATRECORD and RECORD properties all contained what they should. It was only when a certain field was filled in that the data became corrupt. Through much testing we were able to determine which field had to be filled in to cause the corruption but it still made no sense. To illustrate using the AVERY_LABELS table (the client's data is commercially sensitive so we can't use screenshots from their system). In the example below the Cross Reference column references another row in the AVERY_LABELS table and extracts the product description.
So the above is what we expected to see. The below is more like what we were seeing - data that SHOULD have been there ("Removable Laser..." in Cross Ref Product Desc) wasn't - being replaced with the contents of the field above. Data was missing ("Label" in Product Type) and data was incorrect ("6464" in Template Family).
Painstakingly we played with entering data into the client screen - all 6 pages of it - until the error manifested itself when we entered data into a prompt that provided the key for a symbolic to xlate off. We turned on engine logging to see if some event was being triggered that would explain the corruption, but there was nothing other than standard engine flow. On a hunch we went to the system monitor and typed the equivalent of
LIST 100 AVERY_LABELS PRODUCT_DESC XREF_DESC SEQUENCE and were rewarded with something like
which was NOT what we would have expected to see. So we decided that the XREF_DESC formula must have been to blame in some way. Looking at it, it SEEMED to be straightforward enough :-
Until we looked REALLY closely... the column is called PRODUCT_DESC not PRODUCT_DESCS$. When we changed the spelling to the correct one - AVERY_LABELS$PRODUCT_DESC$ everything was right with the world again - the screen displayed correctly and the LIST statement produced
So - what went wrong? To understand this we need to be familiar with how the Window processor actually works with the data from @Record.
A major change in OI over AREV is that when the system WRITEs the current screen contents to disk, it does not simply write the contents of @Record onto disk as in AREV, rather it takes the current row from disk and updates ONLY those columns that feature in the current Window. THEN it writes the row back. This allows the user to have multiple windows open updating separate sections of the same current row.
To do this the Window processor has to maintain its own pseudo @Record, just containing the contents of the current screen. To illustrate using the pseudo code for a READ and populate operation
pseudoRecord = ""
for loopPtr = 1 to controlCount
control = controlList< loopPtr >
dictColumn = get_Property( control , "COLUMN")
pseudoRecord := xlate( dataTable, @Id, dictColumn, "X") : @Fm
next
pseudoRecord[-1, 1] = ""
for loopPtr = 1 to controlCount
control = controlList< loopPtr >
call set_Property( control, "DEPFROP", pseudoRecord< loopPtr >)
next
In the original dictionary item the XLATE destination column was incorrectly spelt, so at compile time in the Table Builder the equate would NOT have been replaced with a column number, but with a blank. The Table Builder compiler before OI 10 does not include the error checking that the System Editor has. So the XREF_DESC formula was resolving to
@Ans = Xlate("AVERY_LABELS", {CROSSREF}, "", "X")
which returns the entire row, not just an individual column. So instead of pseudoRecord containing
1 : @FM : 8 : @FM : 3 : @FM : Xlated 8 : @FM : 2 : @FM : 17 : @FM : 10 : @FM : 16
it contained
1 : @FM : 8 : @FM : 3 : @FM : Xlated 1 - 43 : @FM : 2 : @FM : 17 : @FM : 10 : @FM : 16
thereby pushing the subsequent SET_PROPERTY DEFPROP out of kilter.
Obvious with hindsight but not the easiest bug in the world to track down on a system written by someone else!
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home