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

  1. 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:

    • Place discard in the Read trigger; for more information, see Using discard in the Read Trigger
    • Place the instruction setocc -1 after discard to make the last occurrence the active occurrence.
    • Use $next or compare/next before discard to ensure that Uniface fetches the next occurrence.

    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)
  2. 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)
  3. 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)
  4. 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)
  5. 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)
  6. 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)
  7. 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)