things you should know using discard with stepped hitlists
Author: ulrichmerkel@web.de (ulrich-merkel)
I can't test it for the moment in time,
but I think the behaviour described in http://uniface.communityzero.com/uniface?go=10001877&content=entry&form_id=all is not a wish, but a big bug.
7 Comments
Local Administrator
The described behavior is not considered a bug, but normal behavior. For details see the doc bug 26339 ("$status is 0 after discard even when there are still occurrences to be read"):
"This behavior can be explained by the way the retrieve statement is executed:
The occurrences will only be fetched just before they need to be displayed on the component. So the fetch occurs when needed (gui, setocc). This can also be seen in the in the example [see bug description of 26339] mentioned: change the number of painted occurrences to 5 and look at the proc tracing. :<READ> is fired 3 more times after the loop when 5 occurrences are painted.
Documentation says this:
If the discarded occurrence is not the last occurrence, the next occurrence is made active after a discard. At the moment the discard is executed in the example there is indeed no next occurrence."
And the problem can be avoided by using on of the following solutions:
But I agree that the documentation could be clearer about the behavior of discard in the described circumstance. I'll see what I can do to get this changed.
I hope the provided information is helpful.
Kind regards,
Daniel
Author: diseli (daniel.iseli@uniface.com)
Local Administrator
Hi Daniel,
thanks for the explanation.
I just think about a filter procedure where we take away records after the retrieve
retrieve
setocc 1
-loop-trough-the-entity-checking-$status-greater-1
-if-this-or-that
-discard
-else
-setocc-currocc-+1
-endif
-end-loop-trough-the-entity
looks this may not work with stepped hitlists ??
Author: ulrich-merkel (ulrichmerkel@web.de)
Local Administrator
The 'secret' to this is to use a counter rather than curocc, it's annoying but less prone to this kind of issue. :-
v_counter = 1
setocc ENTITY, v_counter
while($status >0)
if (not good )
discard ENTITY
else
v_counter = v_counter+1
endif
setocc ENTITY, v_counter
endwhile
That way this behaviour is reduced without the need for a setocc -1 at the beginning (and loading everything).
You can throw a
if(v_counter = 100)
discard ENTITY,1,v_counter
v_counter = 1
endif
in as well, to keep the memory usage lower.
Author: Iain Sharp (i.sharp@pcisystems.co.uk)
Local Administrator
plus an old issue when printing:
when you print, NEVER discard up to the actual position,
because print will increment occurences on it's own.
if you discard in the "LEAVE PRINTED OCCURENCE" trigger, only occ 1,3,5,7,9 are printed.
the "correct" way is:
if ($curocc > 1)
discard 1
endif
Author: ulrich-merkel (ulrichmerkel@web.de)
Local Administrator
We normally use
setocc "ent", 1
while($status >0)
if(not good)
setocc "ent",$curocc(ent)+1
if($status>0)
setocc "ent",$curocc(ent)-1
endif
discard "ent"
else
setocc "ent",$curocc(ent)+1
endif
endwhile
Marco
Author: Marco (marco.aquino@dedalus.eu)
Local Administrator
Small correction: the current version of the Uniface Library 9.5 (that can be downloaded from here or can be found here) should be up-to-date. For details seethe paragraph Getting the Next Occurrence:
"Except when used in the Read trigger, discard looks only at occurrences already present in the component (that is, occurrences for which the Read trigger has fired). It is therefore possible for $status to be set to 0 (no next occurrence is available), even though more occurrences are available in the database. To ensure that the next occurrence is retrieved from the database, you can do one of the following:
* Place discard in the Read trigger; for more information, see Using discard in the Read Trigger
* Use setocc $entname, $curocc + 1 after discard. If $status < 0, all occurrences of the hitlist have been fetched; for an example, see Using discard in Batch Process.
* Complete the hitlist before using discard by using the instructions setocc $entname, -1 and setocc $entname, 1 after retrieve.
However, this can have a negative effect on performance because it fetches all the occurrences in the hitlist from the database.
* Use $next or compare/next before discard to ensure that Uniface fetches the next occurrence."
And here's an example about how to use discard (outside the READ trigger) with a stepped hitlist:
"Using discard in Batch Process
The following example shows how to get optimum use of the discard statement in a batch process:
; trigger: Execute
retrieve
if ($status <0)
return ($status)
endif
repeat
discard "ENTITY"
if ($status = 0)
setocc "ENTITY", $curocc("ENTITY") + 1
endif
until ($status < 0)"
I hope the provided information is helpful.
Kind regards,
Daniel
Author: diseli (daniel.iseli@uniface.com)
Local Administrator
Dear All
This is too old "feature" from uniface 5 if i remember well the discard was tricky when you work on hitlist in a discard loop.
We have examine this and we believe that the only safe way do discard in hitlist is to fetch the next occurance before discard the current.
So all these years we use this template code :
SetOcc "ENTNAME" , 1
vnLoopStatus = $Status
While ( vnLoopStatus >= 0 )
;Discard Case If
vbDiscardFlag = 0
If ( DISCARDCASE )
vbDiscardFlag = 1
EndIf
SetOcc "ENTNAME" , $CurOcc (ENTNAME) + 1
vnLoopStatus = $Status
If ( vbDiscardFlag )
If ( vnLoopStatus >= 0 ) ;Lines Remaing In Entity
Discard "ENTNAME" , $CurOcc(ENTNAME) - 1
Else
Discard "ENTNAME" , $CurOcc(ENTNAME)
EndIf
EndIf
EndWhile
Author: jtsagara (jtsagara@logisoft.gr)